您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 质量控制/管理 > 表达式用二叉树表示(1)
数据结构程序报告(3)2011.3.292.需求分析:(1)功能:表达式可以用二叉树表示,对于简单的四则运算,请实现以下功能【1】对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二叉树,并且图示出来(图形的形式)。【2】对于构造好的内部表达式二叉树,按照用户的要求输出相应的前缀表达式(不带括号)、中缀表达式(可以带括号,但不允许冗余括)或后缀表达式(不带括号)。提示:所谓中缀表达式中的冗余括号,就是去掉括号后不影响表达式的计算顺序。例如:“(c+b)+a”中的括号是冗余的,可以表示成不冗余的“c+b+a”。(2)输入输出要求:请输入字符串表达式:树形二叉树(图形显示)中缀表达式为:前缀表达式为:后缀表达式为:3.概要设计:(算法)分成两部分完成:【1】前缀、中缀、后缀表达式-二叉树表达式前缀表达式-二叉树表达式:(a)碰到操作数则把其值赋给相应的新申请的二叉树结点,地址压栈;(b)碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址,分别作为其右指针和左指针,然后再把其地址压栈,最后一个地址即为二叉树的根结点地址。中缀表达式-二叉树表达式:把中缀表达式转换成后缀表达式,然后再建立二叉树。后缀表达式-二叉树表达式:(a)碰到操作数则把其值赋给相应的新申请的二叉树结点,若栈为空则地址压栈,若非空则取栈顶元素,若栈顶元素的左孩子为空则当前结点设为其左孩子,左孩子为满则设为其右孩子再压栈;(b)碰到操作数则把其值赋给相应的新申请的二叉树结点,取栈顶元素,若栈顶元素的左孩子为空则设为其左孩子,左孩子为满则设为其右孩子开始那个元素地址为根结点地址,开始时用变量root保存。【1】二叉树表达式-前缀、中缀、后缀表达式二叉树表达式-前缀表达式:对二叉树表达式进行前序遍历。二叉树表达式-中缀表达式:对二叉树表达式进行中序遍历,若结点操作符的优先级高于其左或右子树,在打印相应的子树之前先打印开括号,在打印相应的子树最后在打印一个闭括号。二叉树表达式-后缀表达式:对二叉树表达式进行后序遍历。建立表达式树就是建立树中的每一个结点,将每一个结点链接起来就是整棵树。而在建立深度低的结点时要将其左右指针指向之前建立的深度比它高一级的结点(如’*’要指向’2’和’3’,而’+’又要指向’*’)。这样我们可以用栈来存放每次建立的结点,按照优先级(表达式为中缀型)或顺序扫描表达式(表达式为波兰式与逆波兰式)建立每一个结点。建立结点的顺序即为表达式求值的顺序。如果扫描到操作数则直接新建一个左右指针为空的结点,并压入结点栈中(存放结点指针)。遇到运算符时首先新建一个结点,然后从栈中依次弹出两个结点,并让新建立的结点的左右指针域指向它们。当所有结点建立完毕时,如果表达式没有错误(这里假设输入表达式正确),这时栈中应该只剩下一个结点,它就是所建立的表达式的根结点。4.详细设计:(具体方法)首先创建一个节点类TNode:包含操作符oper、左孩子left、右孩子right,isOper()判断是否为操作符,getOperOrder()返回运算符op所对应的优先级,freeTree()程序结束销毁二叉树,postOrder()先序遍历,preOrder()后序遍历,inOrder()中序遍历,ExpTree1()后缀表达式生成二叉树,ExpTree3()前缀表达式生成二叉树,ExpTree2()中后缀表达式生成二叉树,count()求值函数,paint()输出函数附程序:#includeiostream#includestack#includequeue#includestring#includemath.husingnamespacestd;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;isizeof(oper);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);coutMemoryfree;}voidpostOrder(TNode*p)//先序遍历{if(p){postOrder(p-left);postOrder(p-right);coutp-oper;}}voidpreOrder(TNode*p)//后序遍历{if(p){coutp-oper;preOrder(p-left);preOrder(p-right);}}voidinOrder(TNode*p)//中序遍历{if(p){if(p-left){if(isOper(p-left-oper)&&getOperOrder(p-left-oper)getOperOrder(p-oper)){cout(;inOrder(p-left);cout);}else{inOrder(p-left);}}coutp-oper;if(p-right){if(isOper(p-right-oper)&&getOperOrder(p-right-oper)=getOperOrder(p-oper)){cout(;inOrder(p-right);cout);}else{inOrder(p-right);}}}}voidExpTree1(TNode*&p,stringstr)//后缀表达式生成二叉树{stackTNode*nodeStack;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++];}}}voidExpTree3(TNode*&p,stringstr)//前缀表达式生成二叉树{stackTNode*nodeStack;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--];}}}voidExpTree2(TNode*&p,stringstr)//中缀表达式转换成后缀表达式生成二叉树{stackchara;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下标加1{Postfixexp+=a.top();a.pop();}a.push(temp);temp=str[i++];}}while(!a.empty()){Postfixexp+=a.top();a.pop();}ExpTree1(p,Postfixexp);}voidcount(TNode*p,int&height,intn)//求值函数{if(p-left==NULL&&p-right==NULL){if(nheight)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;queueTNode*aQueue;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-sh){coutendl;h=pointer-s;}if(pointer-t==1){for(i=0;ipow(2,height-pointer-s)-1;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;}els
本文标题:表达式用二叉树表示(1)
链接地址:https://www.777doc.com/doc-3197107 .html