北工大数据结构上机实验报告3教材.docx
- 文档编号:11174554
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:18
- 大小:28.14KB
北工大数据结构上机实验报告3教材.docx
《北工大数据结构上机实验报告3教材.docx》由会员分享,可在线阅读,更多相关《北工大数据结构上机实验报告3教材.docx(18页珍藏版)》请在冰豆网上搜索。
北工大数据结构上机实验报告3教材
上机题三报告
姓名:
学号:
完成日期:
2015年5月5日
题目:
表达式可以用表达式二义树来表示。
对于简单的四则运算表达式,请实现以下功能;
(1)对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二义树,并且以图示显示出来(字符图或图形的形式)。
(2)对于构造好的内部表达式二叉树,按照用户要求,输出相应的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号).
一、需求分析
1.输入形式、输入值的范围;输入前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号)
2.输出形式^表达式二叉树,前缀表达式、中缀表达式和后缀表达式。
3・程序功能;用表达式二叉树表示表达式,并转换为前缀表达式、中缀表达式或后缀表达式。
4.测试数据
正确的输入输出:
为为为达达达表表表241
错误的输入输出:
请输入字符串表达式:
23+11/304
1/
34
中缀表达式为=1+3/4雪建i轲为=必4后缀衾达式为=134/+
二、概要设计
1.ADT定义
classTNode//W点类
2.主程序流程
3.各程序模块间的调用关系
Main()
求二叉树表达式模块
求前、中、后缀表达式模块
打印树
删除树
三、详细设计
1.实现ADT定义的数据类型
classTNode//节点类
{public:
charoper;//数据域,为简便起见,操作数用单个字符代替
TNode*left;
TNode*right;
ints;intt;〃计算树的层数使用
TNode()//缺省构造函数
{left二right二NULL;
opei-O;
}
TNode(charop)//赋值构造函数
{left二right二NULL;
opei-op;
}
1;
2.算法描述
表达式转化为二叉树
voidpre2tree(TNode*&p,stringstr)//#缀表达式生成二叉树
{碰到操作数则把英值赋给相应的新申请的二叉树结点,地址压栈:
碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址,
分别作为英左指针和右指针,然后再把其地址压栈,最后一个地址即为二叉树的根结点地址。
)
voidpost2tree(TNode*&p^stringstr)//后缀表达式生成二叉树
{〃碰到操作数则把英值赋给相应的新申请的二叉树结点,若栈为空则地址压栈,
〃碰到操作符则把其值赋给相应的新申请的二叉树结点,取栈顶元素,
〃若当前元素的左孩子为空则设为其左孩子,
〃左孩子为满则设为其右孩子,开始那个元素地址为根结点地址,开始时用变量root保存。
}
voidin2tree(TNode*&p,stringstr)//中缀表达式转换成后缀表达式生成二叉树
{从中缀表达式中自左至右依次读入各个字符。
如果读入操作数,直接输出到后缀表达式。
如果读入的是运算符,并且运算符栈为空,则将该运算符宜接进栈:
如果栈不
为空,则比较该运算符和栈顶运算符的优先级。
若该运算符高于栈顶运算符的优先级,则将该运算符直接进栈:
若该运算符低于或等于栈顶运算符的优先级,则将栈中高于或等于该运算符优先
级的元素依次出栈输出到后缀表达式中,然后再将该运算符进栈。
在碰到开括号和栈为空前反复弹出栈中元素
若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时,
/将栈顶元素弹岀到后缀表达式
}
二叉树表达式转化为表达式
voidpostOrdcr(TNode*p)〃先序遍历
{if(P)
{postOrder(p->left);
postOrder(p->right);
cout«p->oper;
)
}
voidpreOrder(TNode*p)//后序遍历
{if(P)
{cout«p->oper;
preOrder(p->left);
preOrder(p->right);
voidinOrder(TNodc幺p)〃中序遍历,同时输出不带冗余括号的中缀表达式
{if(P)
if(p->left)
{if(如果当前节点的左子树是运算符,且运算符优先级低于当前运算符,
那么左边的表达式要先il•算,需要加括号)
{
cout«H(H;
inOrder(p->left);
cout«H)M;
}
else//否则直接输出左子树
inOrdcr(p->left);
}
cout«p->opcr;〃输出当前巧点
if(p->right)
{if(如果当前节点的右子树是运算符,且运算符优先级不高于当前运算符,
那么右边的表达式要先计算,需要加括号)
{
cout«H(n;
inOrder(p->right);
cout«,r)M;
}
else
inOrder(p->right);
四、程序测试
n
Pl
鬧输入字符串表达式,
-*4-2325
3■■:
r
駡输入字符串表达式:
K2+3)*2-5
吃5-
M2石
>3兴
+3+2吃
2*3
<-2第知站迄达2表表表
*3缀缀缀+2虫聲
養输入字符串表达式:
23+2*5-
为为为达达达表表表3缀缀缀2中曹
五、用户使用说明
运行程序后,按照提示选择表达式类型(-1:
前缀表达式;0:
中缀表达式:
1:
后缀表达式)然后输入相应的表达式,回车后可以得到二叉树表达式及出前缀、中缀、后缀表达式
六、源程序
#include
#includc
#includc
#include
#include
usingnamespacestd;
classTNode//节点类
{public:
charoper7/数据域,为简便起见,操作数用单个字符代替
TNode*left;
TNode*right;
ints;intW树的层数使用
TNode()//缺省构造函数
{Ieft=right=NULL;
oper=0;
}
TNode(charop)//赋值构造函数
{left=right=NULL;
oper=op;
}
};
boolisOper(charop)〃判断是否为运算符
{
charoper[]={,(,;)\,+,,'-',
for(inti=0;i i++) {if(op=oper[i]) { returntme; } ) returnfalse; } intgetOperOrder(charop)//返回运算符op所对应的优先级 {//左括号优先级,加减号为,乘除号为,方幕为,右括号,栈底返回switch(op){caser: return1; case屮: case"clum2; case case7: return3;case,A,: return4;default: 〃龙义在栈中的右括号和栈底字符的优先级最低 return0; } ) voidfreeTree(TNode*&p)//递归删除树 { if(p->left! =NULL) freeTree(p->left); if(p->right! =NULL)freeTree(p->right); delete(p); } voidpostOrder(TNode*p)〃先序遍历 {if(P) {postOrder(p->left); postOrder(p->right); cout«p->oper; } } voidpreOrder(TNodc*p)//后序遍历 {if(P) {cout«p->oper; preOrder(p->left); preOrder(p->right); }} voidinOrder(TNode幺p)〃中序遍历,同时输出不带冗余括号的中缀表达式 {if(P) { if(p->left) {//如果当前节点的左子树是运算符,且运算符优先级低于当前运算符, 〃那么左边的表达式要先计算,需要加括号 if(isOper(p->left->opcr)&&gctOpcrOrdcr(p・>lcft・>opcr)vgctOpcrOrdcr(p・>opcr)) { cout«n(n; inOrder(p->left); cout«,i)M; } else//否则直接输岀左子树 inOrdcr(p->left); coulvvp・>opcr;〃输出当前盯点 if(p->right) {〃如果当前节点的右子树是运算符,且运算符优先级不髙于当前运算符, 〃那么右边的表达式要先计算,需要加括号 if(isOper(p->right->opcr)&&gctOpcrOrdcr(p・>righJ>opcr)v=gctOpcrOrdcr(p〉opcr)){ cout«H(n; inOrder(p->right); cout«,,)M; } else inOrder(p->right); } } ) voidpost2tree(TNode*&p,stringstr)//后缀表达式生成二叉树 {//(a)碰到操作数则把其值赋给相应的新申请的二叉树结点,若栈为空则地址压栈, //(b)碰到操作符则把其值赋给相应的新申请的二叉树结点,取栈顶元素, 〃若当前元素的左孩子为空则设为其左孩子, 〃左孩子为满则设为其右孩子,开始那个元素地址为根结点地址,开始时用变量root保存。 stack chartemp; inti=0; temp=str[i++]; whilc(tcmp! =、(y) { if(temp! =\0,&&! isOper(temp))//不是运算符,则进栈 { p=newTNode(temp);//以temp为结点值构造二叉树结点nodeStack.push(p); temp=str[i++]y/读入F—个 } else {〃如果遇到符号,则弹栈,依次设为右节点和左节点 p=newTNode(temp); if(nodcStack.sizeO) { p->right=nodeStack.top();//若非空则弹栈并设为结点的右孩子 nodcStack.popO; if(nodcStack.sizeO) {p->left=nodcStack.top();〃若非空则禅栈并设为结点的左孩子 nodcStack.popO; } nodeStack.push(p); temp=str[i++]; } } } voidpre2tree(TNode*&p.stringstr)//前缀表达式生成二叉树 {//碰到操作数则把其值赋给相应的新申请的二叉树结点,地址压栈: 〃碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址, 〃分别作为其左指针和右指针,然后再把其地址压栈,最后一个地址即为二叉树的根结点地址。 stack chartemp; inti=str.size()-l; temp=str[i-]; while(temp! =f\Or) { if(temp! =\0*&&JisOper(tenip)) {p=newTNode(temp)7/以temp为内容来建立新的结点 nodcStack.push(p); temp=str[i-];} else {p=newTNode(temp); if(nodeStack.size())//栈非空 {p->left=nodeStack.top();〃则栈顶指针所指结点设it成当前结点左孩子 nodcStack.popO; } if(nodcStack.sizc())〃栈非空 {p->right=nodeStack.top()7/则栈顶指针所指结点设置成当前结点右孩子 nodeStack.popO;〃栈顶元素左右孩子指针设置完毕弹岀 } nodeStack.push(p); temp=str[i-]; } }〃当栈空且扫描到最后时,树根由P带回 voidin2tree(TNode*&p.stringstr)//中缀表达式转换成后缀表达式生成二叉树 stack chartemp; stringPostfixexp=,H,; inti=0; temp=str[i++]; whilc(icmp! =、(K) { if(! isOpcr(tcmp))〃操作数则宜接进数据栈 {Postfixexp+=temp; temp=str[i++]; } elseif(temp==,(,)//进栈 { a.push(temp);temp=str|i++J; } elseif(temp=,)') { whilc(a」op()! =()//脱括号 { Postfixexp+=a.top(); a.pop();〃在碰到开括号和栈为空前反复弹岀栈中元素 } a.popO; temp=str[i++); } elseif(temp=,+,lltemp=-1ltemp==,*,lltemp==7)//出栈 { while(! a.empty()&&a.top()! =C&&getOperOrder(a.top())>=getOperOrder(temp)) 〃若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时, //将栈顶元素弹岀到后缀表达式中,并且str下标加 {Postfixexp+=a.top();a.pop();} a.push(temp); temp=str[i++]; } }//endwhile(temp! =W) while(! a.einpty()) {Postfixexp+=a.top(); a.popO; } Postfixexp+=W\ //cout«Postfixexp: post2tree(p.Postfixexp); } voidcount(TNode*pjnt&heightjntn)〃求值函数 {//求树的高度 if(p->left=NULL&&p->righl=NULL) {if(n>height) height=n;} if(p->left! =NULL) count(p->left,height.n+l); if(p->right! =NULL) count(p->right,height.n+1); } voidpaint(TNode水p)//打印树 { intheight=O; inth=0; inti; usingstd: : queue: queue count(p,height」); TNode*pointer=p; TNode*lastpointer; if(pointer) {pointer->s=l; pointer->t=l; aQueue.push(pointer);} while(! aQueue.empty()) {lastpointer=pointer; pointer=aQueue.front(); aQucue.popO; if(pointer->s>h) {cout«endl; h=pointer->s;} if(pointer->t==l) {for(i=0;i cout«H”;} elseif(lastpointer->s! =pointer->s){ for(i=0;i<(pointer->t-1)*(pow(2,height-pointer->s+1)-1)+(pointer->t-1)-1+pow(2.height-pointer->s);i++) cout«,rM;} else {for(i=0;i<(pointer->t-lastpointer->t)*(pow(2,height-pointer->s+1)-1)+(pointer->t-lastpointer->t)-l;i++) cout«HH;} cout«pointer->opcr; if(pointer->left! =NULL){ pointer->left->s=pointer->s+1; pointer->left->t=pointer->t*2-l; aQueue.push(pointer->Ieft);} if(pointer->right! =NULL){ pointer->right->s=pointer->s+1;pointer->right->t=pointer->t*2; aQueue.push(pointer->right); }}} intmain() { stringexpression; TNode*tree; cout«"请输入表达式类型,前缀表达式输入-1,中缀表达式输入0后缀表达式输入lM«endl; intflag; cin»flag; coutvv"请输入字符串表达式: H«endl; cin»expression: if(flag=-l)//那么是前缀表达式 pre2tree(tree,expression); elseif(flag==l)//那么是后缀表达式 post2tree(tree,expression); else//否则中缀表达式 in2tree(tree,expression); paint(trec); cout«endl: cout«"中缀表达式为: “; inOrder(tree); cout«endl; cout«"前缀表达式为: “; preOrder(tree); cout«endl; cout«"后缀表达式为: "; postOrder(tree); cout«endl;freeTree(tree);cout«endl; return0;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北工大 数据结构 上机 实验 报告 教材
![提示](https://static.bdocx.com/images/bang_tan.gif)