1、表达式二叉树表达式二叉树一、需求分析1、对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二叉树,并且图示出来(图形的形式)。2、对于构造好的内部表达式二叉树,按照用户的要求输出相应的前缀表达式(不带括号)、中缀表达式(可以带括号,但不允许冗余括)或后缀表达式(不带括号)。二、概要设计1、ADT定义class Node /节点类 public:char oper;/数据域,为简便起见,操作数用单个字符代替Node *left; /左孩子Node *right;/右孩子int s;int t;/计算树的层数使用Node() l
2、eft=right=NULL; oper=0; Node(char op) left=right=NULL; oper=op;bool isOper(char op)/判断是否为运算符void postOrder(Node *p) /先序遍历void preOrder(Node *p) /后序遍历void inOrder(Node *p)/中序遍历,同时输出不带冗余括号的中缀表达式void post2tree(Node *&p,string str)/后缀表达式生成二叉树void pre2tree(Node *&p, string str)/前缀表达式生成二叉树void in2tree(Nod
3、e *&p, string str)/中缀表达式转换成后缀表达式生成二叉树void paint(Node *p)/打印树void count(Node *p,int &height,int n)/求数的层数,以便与打印树void freeTree(Node *&p) /递归删除树int getOperOrder(char op)/返回运算符op所对应的优先级2、主程序和各模块的调用int main() string expression; Node *tree; cout前缀表达式-1 中缀表达式0 后缀表达式1flag; cout请输入表达式:expression; if(flag=-1)/
4、前缀表达式 pre2tree(tree,expression); else if(flag=1)/后缀表达式 post2tree(tree,expression); else /中缀表达式 in2tree(tree,expression); paint(tree); coutendl; cout前缀表达式为:; preOrder(tree); coutendl; cout中缀表达式为:; inOrder(tree); coutendl; cout后缀表达式为:; postOrder(tree); coutendl; freeTree(tree); coutendl;return 0; 三、详细
5、设计1、表达式转化为二叉树(1)前缀表达式:从后往前扫描 遇到操作数,把它赋给新建立的二叉树结点,入栈; 遇到运算符,把它赋给新建立的二叉树的节点。如果栈非空,从栈中弹出一个元素,把栈顶指针所指结点设为当前结点的左孩子,如果栈非空,再从栈中弹出一个元素,把栈顶指针所指结点设置为当前结点的右孩子,然后把当前节点压栈,最后一个元素就是二叉树的根结点。(2)中缀表达式:把中缀表达式转换成后缀表达式,然后再生成二叉树。 定义一个运算符栈,并输入一个中缀表达式,然后从中缀表达式中自左至右依次读入各个字符。 如果读入操作数,直接输出到后缀表达式。 如果读入的是运算符,并且运算符栈为空,则将该运算符直接进栈
6、;如果栈不为空, 则 比较该运算符和栈顶运算符的优先级。若该运算符高于栈顶运算符的优先级,则将该运算符直接进栈; 若该运算符低于或等于栈顶运算符的优先级,则将栈中高于或等于该运算符优先级的元 素依次出栈输出到后缀表达式中,然后再将该运算符进栈。 如果读入的是开括号“(”,则直接进栈;如果读入的是闭括号“)”,则一直出栈并输出到后缀表达式,直到遇到一个开括号“(”为止。开括号“(”和闭括号“)”均不输出到后缀表达式。 重复(2)(3)(4)步,直到中缀表达式结束,然后将栈中剩余的所有运算符依次出栈。(3)后缀表达式:从前往后扫描碰到操作数则把它赋给相应的新建立的二叉树结点,若栈为空则入栈,碰到运
7、算符则把它赋给相应的新建立的二叉树结点,若当前结点的左孩子为空则设为其左孩子,左孩子为满则设为其右孩子。开始结点为根结点。2、二叉树表达式转化为表达式(1)前缀表达式:对二叉树表达式进行前序遍历。依次输出各结点。(2)中缀表达式:对二叉树表达式进行中序遍历。 如果当前结点的左子树是运算符,且运算符优先级低于当前运算符,那么左边的表达式要先计算,需要加括号,否则直接输出左子树;如果当前结点的右子树是运算符,且运算符优先级不高于当前运算符,那么右边的表达式要先计算,需要加括号,否则直接输出右子树。依次输出各结点。(3)后缀表达式:对二叉树表达式进行后序遍历。依次输出各结点。四、程序测试五、源程序#
8、include #include #include #include #includeusing namespace std;class Node/结点类 public:char oper;Node *left;Node *right;int s;int t;Node() left=right=NULL; oper=0; Node(char op) left=right=NULL; oper=op;bool isOper(char op)/判断是否为运算符char oper=(,),+,-,*,/,;for(int i=0;ileft!=NULL) freeTree(p-left); if(p
9、-right!=NULL) freeTree(p-right); delete(p); void postOrder(Node *p) /先序遍历 if(p) postOrder(p-left); postOrder(p-right); coutoper; void preOrder(Node *p) /后序遍历 if(p) coutoper; preOrder(p-left); preOrder(p-right); void inOrder(Node *p)/中序遍历,同时输出不带冗余括号的中缀表达式 if(p) if(p-left) /如果当前节点的左子树是运算符,且运算符优先级低于当前运
10、算符, /那么左边的表达式要先计算,需要加括号 if(isOper(p-left-oper)& getOperOrder(p-left-oper)oper) coutleft); coutleft); coutoper;/输出当前节点 if(p-right) /如果当前节点的右子树是运算符,且运算符优先级不高于当前运算符, /那么右边的表达式要先计算,需要加括号 if(isOper(p-right-oper)& getOperOrder(p-right-oper)oper) coutright); coutright); void post2tree(Node *&p,string str)/
11、后缀表达式生成二叉树 stack nodeStack;/用于保存节点指针的栈 char temp; int i=0; temp=stri+; while(temp!=0) if(temp!=0&!isOper(temp)/不是运算符,则进栈 p=new Node(temp);/以temp为结点值构造二叉树结点 nodeStack.push(p); temp=stri+;/读入下一个 else /如果遇到符号,则出栈,依次设为右节点和左节点 p=new Node(temp); if(nodeStack.size() p-right=nodeStack.top();/若非空则出栈并设为结点的右孩子
12、 nodeStack.pop(); if(nodeStack.size() p-left=nodeStack.top();/若非空则出栈并设为结点的左孩子 nodeStack.pop(); nodeStack.push(p); temp=stri+; void pre2tree(Node *&p, string str)/前缀表达式生成二叉树 stack nodeStack; char temp; int i=str.size()-1; temp=stri-; while(temp!=0) if(temp!=0&!isOper(temp) p=new Node(temp);/以temp为内容来
13、建立新的结点 nodeStack.push(p); temp=stri-; else p=new Node(temp); if(nodeStack.size()/栈非空 p-left=nodeStack.top(); /则栈顶指针所指结点设置成当前结点左孩子 nodeStack.pop(); if(nodeStack.size()/栈非空 p-right=nodeStack.top();/则栈顶指针所指结点设置成当前结点右孩子 nodeStack.pop();/栈顶元素左右孩子指针设置完毕弹出 nodeStack.push(p); temp=stri-; void in2tree(Node *
14、&p, string str)/中缀表达式转换成后缀表达式生成二叉树 stack a; char temp; string Postfixexp=; int i=0; temp=stri+; while(temp!=0) if(!isOper(temp)/操作数则直接进数据栈 Postfixexp+=temp; temp=stri+; else if(temp=()/进栈 a.push(temp); temp=stri+; else if(temp=) while(a.top()!=()/脱括号 Postfixexp+=a.top(); a.pop();/在碰到开括号和栈为空前反复弹出栈中元素
15、 a.pop(); temp=stri+; else if(temp=+|temp=-|temp=*|temp=/)/出栈 while(!a.empty()&a.top()!=(&getOperOrder(a.top()=getOperOrder(temp) /若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时 Postfixexp+=a.top(); a.pop(); a.push(temp); temp=stri+; /end while(temp!=0) while(!a.empty() Postfixexp+=a.top(); a.pop(); Postfixexp+=0; /c
16、outleft=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);void paint(Node *p)/打印树 int height=0; int h=0; int i; using std:queue; queue aQueue; count(p,height,1);Node *pointer=p; Node *lastpointer; if(pointer) pointer-s=1;
17、pointer-t=1; aQueue.push(pointer); while(!aQueue.empty() lastpointer=pointer; pointer=aQueue.front(); aQueue.pop(); if(pointer-sh) couts; if(pointer-t=1) for(i=0;is)-1;i+) couts!=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 ; else for(i=0;it-
18、lastpointer-t)*(pow(2,height-pointer-s+1)-1)+(pointer-t-lastpointer-t)-1;i+) cout ; coutoper; 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(poin
19、ter-right); int main() string expression; Node *tree; cout前缀表达式-1 中缀表达式0 后缀表达式1flag; cout请输入表达式:expression; if(flag=-1)/那么是前缀表达式 pre2tree(tree,expression); else if(flag=1)/那么是后缀表达式 post2tree(tree,expression); else /否则中缀表达式 in2tree(tree,expression); paint(tree); coutendl; cout前缀表达式为:; preOrder(tree); coutendl; cout中缀表达式为:; inOrder(tree); coutendl; cout后缀表达式为:; postOrder(tree); coutendl; freeTree(tree); coutendl; return 0;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1