北工大数据结构上机实验报告3.docx
- 文档编号:5384681
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:18
- 大小:103.54KB
北工大数据结构上机实验报告3.docx
《北工大数据结构上机实验报告3.docx》由会员分享,可在线阅读,更多相关《北工大数据结构上机实验报告3.docx(18页珍藏版)》请在冰豆网上搜索。
北工大数据结构上机实验报告3
上机题三报告
姓名:
学号:
完成日期:
2015年5月5日
题目:
表达式可以用表达式二叉树来表示。
对于简单的四则运算表达式,请实现以下功能;
(1)对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二叉树,并且以图示显示出来(字符图或图形的形式)。
(2)对于构造好的内部表达式二叉树,按照用户要求,输出相应的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号).
一、需求分析
1.输入形式、输入值的范围;输入前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号)
2.输出形式;表达式二叉树,前缀表达式、中缀表达式和后缀表达式。
3.程序功能;用表达式二叉树表示表达式,并转换为前缀表达式、中缀表达式或后缀表达式。
4.测试数据
正确的输入输出:
错误的输入输出:
二、概要设计
1.ADT定义
classTNode//节点类
2.主程序流程
3.
是
否
是否为前缀表达式
是否为后缀表达式
否
4.各程序模块间的调用关系
三、详细设计
1.实现ADT定义的数据类型
classTNode//节点类
{public:
charoper;//数据域,为简便起见,操作数用单个字符代替
TNode*left;
TNode*right;
ints;intt;//计算树的层数使用
TNode()//缺省构造函数
{left=right=NULL;
oper=0;
}
TNode(charop)//赋值构造函数
{left=right=NULL;
oper=op;
}
};
2.算法描述
表达式转化为二叉树
voidpre2tree(TNode*&p,stringstr)//前缀表达式生成二叉树
{碰到操作数则把其值赋给相应的新申请的二叉树结点,地址压栈;
碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址,
分别作为其左指针和右指针,然后再把其地址压栈,最后一个地址即为二叉树的根结点地址。
}
voidpost2tree(TNode*&p,stringstr)//后缀表达式生成二叉树
{//碰到操作数则把其值赋给相应的新申请的二叉树结点,若栈为空则地址压栈,
//碰到操作符则把其值赋给相应的新申请的二叉树结点,取栈顶元素,
//若当前元素的左孩子为空则设为其左孩子,
//左孩子为满则设为其右孩子,开始那个元素地址为根结点地址,开始时用变量root保存。
}
voidin2tree(TNode*&p,stringstr)//中缀表达式转换成后缀表达式生成二叉树
{从中缀表达式中自左至右依次读入各个字符。
如果读入操作数,直接输出到后缀表达式。
如果读入的是运算符,并且运算符栈为空,则将该运算符直接进栈;如果栈不为空,则比较该运算符和栈顶运算符的优先级。
若该运算符高于栈顶运算符的优先级,则将该运算符直接进栈;
若该运算符低于或等于栈顶运算符的优先级,则将栈中高于或等于该运算符优先级的元素依次出栈输出到后缀表达式中,然后再将该运算符进栈。
在碰到开括号和栈为空前反复弹出栈中元素
若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时,
/将栈顶元素弹出到后缀表达式
}
二叉树表达式转化为表达式
voidpostOrder(TNode*p)//先序遍历
{if(p)
{postOrder(p->left);
postOrder(p->right);
cout<
}
}
voidpreOrder(TNode*p)//后序遍历
{if(p)
{cout<
preOrder(p->left);
preOrder(p->right);
}}
voidinOrder(TNode*p)//中序遍历,同时输出不带冗余括号的中缀表达式
{if(p)
{
if(p->left)
{if(如果当前节点的左子树是运算符,且运算符优先级低于当前运算符,
那么左边的表达式要先计算,需要加括号)
{
cout<<"(";
inOrder(p->left);
cout<<")";
}
else//否则直接输出左子树
inOrder(p->left);
}
cout<
if(p->right)
{if(如果当前节点的右子树是运算符,且运算符优先级不高于当前运算符,
那么右边的表达式要先计算,需要加括号)
{
cout<<"(";
inOrder(p->right);
cout<<")";
}
else
inOrder(p->right);
}
}
四、程序测试
五、用户使用说明
运行程序后,按照提示选择表达式类型(-1:
前缀表达式;0:
中缀表达式;1:
后缀表达式)
然后输入相应的表达式,回车后可以得到二叉树表达式及出前缀、中缀、后缀表达式
六、源程序
#include
#include
#include
#include
#include
usingnamespacestd;
classTNode//节点类
{public:
charoper;//数据域,为简便起见,操作数用单个字符代替
TNode*left;
TNode*right;
ints;intt;//计算树的层数使用
TNode()//缺省构造函数
{left=right=NULL;
oper=0;
}
TNode(charop)//赋值构造函数
{left=right=NULL;
oper=op;
}
};
boolisOper(charop)//判断是否为运算符
{
charoper[]={'(',')','+','-','*','/','^'};
for(inti=0;i {if(op==oper[i]) { returntrue; } } returnfalse; } intgetOperOrder(charop)//返回运算符op所对应的优先级 {//左括号优先级,加减号为,乘除号为,方幂为,右括号,栈底返回 switch(op){ case'(': return1; case'+': case'-': return2; case'*': case'/': return3; case'^': 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< } } voidpreOrder(TNode*p)//后序遍历 {if(p) {cout< preOrder(p->left); preOrder(p->right); }} voidinOrder(TNode*p)//中序遍历,同时输出不带冗余括号的中缀表达式 {if(p) { if(p->left) {//如果当前节点的左子树是运算符,且运算符优先级低于当前运算符, //那么左边的表达式要先计算,需要加括号 if(isOper(p->left->oper)&&getOperOrder(p->left->oper) { cout<<"("; inOrder(p->left); cout<<")"; } else//否则直接输出左子树 inOrder(p->left); } cout< if(p->right) {//如果当前节点的右子树是运算符,且运算符优先级不高于当前运算符, //那么右边的表达式要先计算,需要加括号 if(isOper(p->right->oper)&&getOperOrder(p->right->oper)<=getOperOrder(p->oper)) { cout<<"("; inOrder(p->right); cout<<")"; } else inOrder(p->right); } } } voidpost2tree(TNode*&p,stringstr)//后缀表达式生成二叉树 {//(a)碰到操作数则把其值赋给相应的新申请的二叉树结点,若栈为空则地址压栈, //(b)碰到操作符则把其值赋给相应的新申请的二叉树结点,取栈顶元素, //若当前元素的左孩子为空则设为其左孩子, //左孩子为满则设为其右孩子,开始那个元素地址为根结点地址,开始时用变量root保存。 stack chartemp; inti=0; temp=str[i++]; while(temp! ='\0') { if(temp! ='\0'&&! isOper(temp))//不是运算符,则进栈 { p=newTNode(temp);//以temp为结点值构造二叉树结点 nodeStack.push(p); temp=str[i++];//读入下一个 } else {//如果遇到符号,则弹栈,依次设为右节点和左节点 p=newTNode(temp); if(nodeStack.size()) { p->right=nodeStack.top();//若非空则弹栈并设为结点的右孩子 nodeStack.pop(); } if(nodeStack.size()) { p->left=nodeStack.top();//若非空则弹栈并设为结点的左孩子 nodeStack.pop(); } nodeStack.push(p); temp=str[i++]; } } } voidpre2tree(TNode*&p,stringstr)//前缀表达式生成二叉树 {//碰到操作数则把其值赋给相应的新申请的二叉树结点,地址压栈; //碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址, //分别作为其左指针和右指针,然后再把其地址压栈,最后一个地址即为二叉树的根结点地址。 stack chartemp; inti=str.size()-1; temp=str[i--]; while(temp! ='\0') { if(temp! ='\0'&&! isOper(temp)) {p=newTNode(temp);//以temp为内容来建立新的结点 nodeStack.push(p); temp=str[i--];} else {p=newTNode(temp); if(nodeStack.size())//栈非空 {p->left=nodeStack.top();//则栈顶指针所指结点设置成当前结点左孩子 nodeStack.pop(); } if(nodeStack.size())//栈非空 {p->right=nodeStack.top();//则栈顶指针所指结点设置成当前结点右孩子 nodeStack.pop();//栈顶元素左右孩子指针设置完毕弹出 } nodeStack.push(p); temp=str[i--]; } } }//当栈空且扫描到最后时,树根由P带回 voidin2tree(TNode*&p,stringstr)//中缀表达式转换成后缀表达式生成二叉树 { stack chartemp; stringPostfixexp=""; inti=0; temp=str[i++]; while(temp! ='\0') { if(! isOper(temp))//操作数则直接进数据栈 {Postfixexp+=temp; temp=str[i++]; } elseif(temp=='(')//进栈 { a.push(temp); temp=str[i++]; } elseif(temp==')') { while(a.top()! ='(')//脱括号 { Postfixexp+=a.top(); a.pop();//在碰到开括号和栈为空前反复弹出栈中元素 } a.pop(); temp=str[i++]; } elseif(temp=='+'||temp=='-'||temp=='*'||temp=='/')//出栈 { while(! a.empty()&&a.top()! ='('&&getOperOrder(a.top())>=getOperOrder(temp)) //若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时, //将栈顶元素弹出到后缀表达式中,并且str下标加 {Postfixexp+=a.top();a.pop();} a.push(temp); temp=str[i++]; } }//endwhile(temp! ='\0') while(! a.empty()) {Postfixexp+=a.top(); a.pop(); } Postfixexp+='\0'; //cout< post2tree(p,Postfixexp); } voidcount(TNode*p,int&height,intn)//求值函数 {//求树的高度 if(p->left==NULL&&p->right==NULL) {if(n>height) height=n;} if(p->left! =NULL) count(p->left,height,n+1); if(p->right! =NULL) count(p->right,height,n+1); } voidpaint(TNode*p)//打印树 { intheight=0; inth=0; inti; usingstd: : queue; queue count(p,height,1); TNode*pointer=p; TNode*lastpointer; if(pointer) {pointer->s=1; pointer->t=1; aQueue.push(pointer);} while(! aQueue.empty()) {lastpointer=pointer; pointer=aQueue.front(); aQueue.pop(); if(pointer->s>h) {cout< h=pointer->s;} if(pointer->t==1) {for(i=0;i cout<<"";} 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<<"";} else {for(i=0;i<(pointer->t-lastpointer->t)*(pow(2,height-pointer->s+1)-1)+(pointer->t-lastpointer->t)-1;i++) cout<<"";} cout< if(pointer->left! =NULL){ pointer->left->s=pointer->s+1; pointer->left->t=pointer->t*2-1; aQueue.push(pointer->left);} 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后缀表达式输入1"< intflag; cin>>flag; cout<<"请输入字符串表达式: "< cin>>expression; if(flag==-1)//那么是前缀表达式 pre2tree(tree,expression); elseif(flag==1)//那么是后缀表达式 post2tree(tree,expression); else//否则中缀表达式 in2tree(tree,expression); paint(tree); cout< cout<<"中缀表达式为: "; inOrder(tree); cout< cout<<"前缀表达式为: "; preOrder(tree); cout< cout<<"后缀表达式为: "; postOrder(tree); cout< freeTree(tree); cout< return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北工大 数据结构 上机 实验 报告