1、北工大数据结构上机实验报告3教材上机题三报告姓名:学号:完成日期:2015年5月5日题目:表达式可以用表达式二义树来表示。对于简单的四则运算表达式,请实现 以下功能;(1)对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带 括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二义树, 并且以图示显示出来(字符图或图形的形式)。(2)对于构造好的内部表达式二叉树,按照用户要求,输出相应的前缀表达式 (不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号).一、需求分析1.输入形式、输入值的范围;输入前缀表达式(不带括号)、中缀表达式(可 以带括号)或后缀表达式(不带括号)
2、2.输出形式表达式二叉树,前缀表达式、中缀表达式和后缀表达式。3程序功能;用表达式二叉树表示表达式,并转换为前缀表达式、中缀表达式 或后缀表达式。4.测试数据正确的输入输出:为为为 达达达 表表表 2 41错误的输入输出:请输入字符串表达式:23+11/3041 /3 4中缀表达式为=1+3/4 雪建i轲为=必4 后缀衾达式为=134/ +二、概要设计1. ADT定义class TNode/W 点类2.主程序流程3.各程序模块间的调用关系Main ()求二叉树表 达式模块求前、中、后缀 表达式模块打印树删除树三、详细设计1.实现ADT定义的数据类型class TNode/节点类 public:
3、char oper;/数据域,为简便起见,操作数用单个字符代替TNode *left;TNode *right;int s;int t;计算树的层数使用TNode()/缺省构造函数 left 二 right二NULL;opei-O;TNode(char op)/赋值构造函数 left 二 right 二 NULL;opei-op;1;2.算法描述表达式转化为二叉树void pre2tree(TNode *&p, string str)/#缀表达式生成二叉树 碰到操作数则把英值赋给相应的新申请的二叉树结点,地址压栈:碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址,分别作为英左指
4、针和右指针,然后再把其地址压栈,最后一个地址即为二叉树的 根结点地址。)void post2tree(TNode *&pstring str)/后缀表达式生成二叉树 碰到操作数则把英值赋给相应的新申请的二叉树结点,若栈为空则地址压栈,碰到操作符则把其值赋给相应的新申请的二叉树结点,取栈顶元素,若当前元素的左孩子为空则设为其左孩子,左孩子为满则设为其右孩子,开始那个元素地址为根结点地址,开始时用变量 root保存。void in2tree(TNode *&p, string str)/中缀表达式转换成后缀表达式生成二叉树 从中缀表达式中自左至右依次读入各个字符。如果读入操作数,直接输出到后缀表达
5、式。如果读入的是运算符,并且运算符栈为空,则将该运算符宜接进栈:如果栈不为空,则比较该运算符和栈顶运算符的优先级。若该运算符高于栈顶运算符的优先级,则将该运算符直接进栈:若该运算符低于或等于栈顶运算符的优先级,则将栈中高于或等于该运算符优先级的元素依次出栈输出到后缀表达式中,然后再将该运算符进栈。在碰到开括号和栈为空前反复弹出栈中元素若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时,/ 将栈顶元素弹岀到后缀表达式二叉树表达式转化为表达式void postOrdcr(TNode *p)先序遍历 if(P) postOrder(p-left);postOrder(p-right);cout
6、p-oper;)void preOrder(TNode *p)/后序遍历 if(P) coutp-oper;preOrder(p-left);preOrder(p-right);void inOrder(TNodc幺p)中序遍历,同时输出不带冗余括号的中缀表达式 if(P)if(p-left)if(如果当前节点的左子树是运算符,且运算符优先级低于当前运算符,那么左边的表达式要先il算,需要加括号)coutH(H;inOrder(p-left);coutH)M;else/否则直接输出左子树inOrdcr(p-left);coutp-opcr;输出当前巧点if(p-right) if(如果当前节点
7、的右子树是运算符,且运算符优先级不高于当前运算符,那么右边的表达式要先计算,需要加括号)coutH(n;inOrder(p-right);cout,r)M;elseinOrder(p-right);四、程序测试nPl鬧输入字符串表达式,-*4-23253 :r駡输入字符串表达式:K2+3 )*2-5吃5 -M2石 3兴+3+2吃2*3 -2 第知 站迄达 2表表表* 3缀缀缀 + 2虫聲養输入字符串表达式:23+2*5-为为为 达达达 表表表 3缀缀缀 2中曹五、 用户使用说明运行程序后,按照提示选择表达式类型(-1:前缀表达式;0:中缀表达式:1:后缀表达式) 然后输入相应的表达式,回车后可
8、以得到二叉树表达式及出前缀、中缀、后缀表达式六、 源程序#include #includc #includc #include #includeusing namespace std;class TNode/ 节点类 public:char oper7/数据域,为简便起见,操作数用单个字符代替TNode *left;TNode *right;int s;int W树的层数使用TNode()/缺省构造函数 Ieft=right=NULL;oper=0;TNode(char op)/赋值构造函数 left=right=NULL;oper=op;bool isOper(char op)判断是否为运算
9、符char oper=,(,;),+,-,for(int i=0;ileft!=NULL)freeTree(p-left);if(p-right!=NULL) freeTree(p-right);delete(p);void postOrder(TNode *p) 先序遍历 if(P) postOrder(p-left);postOrder(p-right);coutp-oper;void preOrder(TNodc *p) /后序遍历 if(P) coutp-oper;preOrder(p-left);preOrder(p-right);void inOrder(TNode幺p)中序遍历,
10、同时输出不带冗余括号的中缀表达式 if(P)if(p-left)/如果当前节点的左子树是运算符,且运算符优先级低于当前运算符,那么左边的表达式要先计算,需要加括号if(isOper(p-left-opcr)& gctOpcrOrdcr(plcftopcr)vgctOpcrOrdcr(popcr)coutn(n;inOrder(p-left);cout,i)M;else/否则直接输岀左子树inOrdcr(p-left);coulvvpopcr;输出当前盯点if(p-right) 如果当前节点的右子树是运算符,且运算符优先级不髙于当前运算符,那么右边的表达式要先计算,需要加括号if(isOper(
11、p-right-opcr)& gctOpcrOrdcr(prighJopcr)v=gctOpcrOrdcr(popcr) coutH(n;inOrder(p-right);cout,)M;elseinOrder(p-right);)void post2tree(TNode *&p,string str)/后缀表达式生成二叉树/ (a)碰到操作数则把其值赋给相应的新申请的二叉树结点,若栈为空则地址压栈,/ (b)碰到操作符则把其值赋给相应的新申请的二叉树结点,取栈顶元素,若当前元素的左孩子为空则设为其左孩子,左孩子为满则设为其右孩子,开始那个元素地址为根结点地址,开始时用变量root保 存。st
12、ack nodeStack;/用于保存节点指针的栈char temp;int i=0;temp=stri+;whilc(tcmp!=、(y)if(temp!=0,&!isOper(temp)/不是运算符,则进栈p=new TNode(temp);/以temp为结点值构造二叉树结点 nodeStack.push(p);temp=stri+y/读入 F个else 如果遇到符号,则弹栈,依次设为右节点和左节点p=new TNode(temp);if(nodcStack.sizeO)p-right=nodeStack.top();/若非空则弹栈并设为结点的右孩子nodcStack.popO;if(no
13、dcStack.sizeO) p-left=nodcStack.top();若非空则禅栈并设为结点的左孩子nodcStack.popO;nodeStack.push(p);temp=stri+;void pre2tree(TNode *&p. string str)/前缀表达式生成二叉树/碰到操作数则把其值赋给相应的新申请的二叉树结点,地址压栈:碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址,分别作为其左指针和右指针,然后再把其地址压栈,最后一个地址即为二叉树的根结 点地址。stack nodeStack;char temp;int i=str.size()-l;temp=s
14、tri-;while(temp!=fOr)if(temp!=0*& JisOper(tenip) p=new TNode(temp)7/以temp为内容来建立新的结点nodcStack.push(p);temp=stri-;else p=new TNode(temp);if(nodeStack.size()/ 栈非空 p-left=nodeStack.top(); 则栈顶指针所指结点设it成当前结点左孩子nodcStack.popO;if(nodcStack.sizc() 栈非空 p-right=nodeStack.top( )7/则栈顶指针所指结点设置成当前结点右孩子nodeStack.po
15、pO;栈顶元素左右孩子指针设置完毕弹岀nodeStack.push(p);temp=stri-;当栈空且扫描到最后时,树根由P带回void in2tree(TNode *&p. string str)/中缀表达式转换成后缀表达式生成二叉树stack a;char temp;string Postfixexp=,H,;int i=0;temp=stri+;whilc(icmp!=、(K)if( !isOpcr(tcmp)操作数则宜接进数据栈 Postfixexp+=temp;temp=stri+;else if(temp=,(,)/进栈a.push(temp); temp=str|i+J;els
16、e if(temp=,)whilc(aop( )!=()/ 脱括号Postfixexp+=a.top();a.pop();在碰到开括号和栈为空前反复弹岀栈中元素a.popO;temp=stri+);else if(temp=,+,lltemp=-1ltemp=,*,lltemp=7)/ 出栈while(!a.empty()&a.top()!=C&getOperOrder(a.top()=getOperOrder(temp)若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时,/将栈顶元素弹岀到后缀表达式中,并且str下标加 Postfixexp+=a.top(); a.pop(); a.p
17、ush(temp);temp=stri+;/end while(temp!=W)while(!a.einpty() Postfixexp+=a.top();a.popO;Postfixexp+=W/coutPostfixexp:post2tree(p.Postfixexp);void count(TNode *pjnt &heightjnt n)求值函数/求树的高度if(p-left=NULL&p-righl=NULL) if(nheight)height=n;if(p-left!=NULL)count(p-left,height.n+l);if(p-right!=NULL)count(p-r
18、ight,height.n+1);void paint(TNode 水p)/打印树int height=O;int h=0;int i;using std:queue:queue aQueue: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-sh)c
19、outendl;h=pointer-s;if(pointer-t=l)for(i=0;is)-1 ;i+)coutH ”;else if(lastpointer-s!=pointer-s)for(i=0;it-1 )*(pow(2,height-pointer-s+1 )-1 )+(pointer-t-1 )-1 +pow(2.height-pointer- s);i+)cout,r M; else for(i=0;it-lastpointer-t)*(pow(2,height-pointer-s+1 )-1 )+(pointer-t-lastpointer-t)- l;i+)coutH H;
20、 coutpointer-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); int main()string expression;TNode *tree;cout请输入表达式类型,前缀表达式输入-1,中缀表达式
21、输入0后缀表达式输入 lMendl;int flag;cinflag;coutvv请输入字符串表达式:Hendl;cinexpression:if(flag=-l)/那么是前缀表达式pre2tree(tree,expression);else if(flag=l)/那么是后缀表达式post2tree(tree,expression);else /否则中缀表达式in2tree(tree,expression);paint(trec);coutendl:cout中缀表达式为:“;inOrder(tree);coutendl;cout前缀表达式为:“;preOrder(tree);coutendl;cout后缀表达式为:;postOrder(tree);coutendl; freeTree(tree); coutendl;return 0;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1