表达式树

来源:互联网 发布:移动有网络机顶盒吗 编辑:程序博客网 时间:2024/06/10 20:05

从标准输入中读入一个整数算术运算表达式,如24 / ( 1 + 2 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 )= ,计算表达式结果,并输出。
要求:
1、表达式运算符只有+、-、*、/,表达式末尾的=字符表示表达式输入结束,表达式中可能会出现空格;
2、表达式中会出现圆括号,括号可能嵌套,不会出现错误的表达式;
3、出现除号/时,以整数相除进行运算,结果仍为整数,例如:5/3结果应为1。
4、要求采用表达式树来实现表达式计算。
表达式树(expression tree):
我们已经知道了在计算机中用后缀表达式和栈来计算中缀表达式的值。在计算机中还有一种方式是利用表达式树来计算表达式的值。表达式树是这样一种树,其根节点为操作符,非根节点为操作数,对其进行中序遍历将计算表达式的值。由后缀表达式生成表达式树的方法如下:
l 读入一个符号:
l 如果是操作数,则建立一个单节点树并将指向他的指针推入栈中;
l 如果是运算符,就从栈中弹出指向两棵树T1和T2的指针(T1先弹出)并形成一棵新树,树根为该运算符,它的左、右子树分别指向T2和T1,然后将新树的指针压入栈中。
例如输入的后缀表达为:

ab+cde+**

则生成的表达式树为:

【输入形式】
从键盘输入一个以=结尾的整数算术运算表达式。操作符和操作数之间可以有空格分隔。

【输出形式】
首先在屏幕上输出表达式树根、左子节点及右子节点上的运算符或操作数,中间由一个空格分隔,最后有一个回车(如果无某节点,则该项不输出)。然后输出表达式计算结果。
【样例输入】
24 / ( 1 + 2 + 36 / 6 / 2 - 2) * ( 12 / 2 / 2 ) =
【样例输出】
* / /
18

【样例说明】
按照运算符及括号优先级依次计算表达式的值。在生成的表达树中,*是根节点的运算符,/ 是根节点的左子节点上运算符,/是根节点的右子节点上运算符,按题目要求要输出。

本题来源于北航数据结构Judge网站,各位北航小胖油不要照抄哦!作业自己写,Judge网站自带查重……

#include<iostream>#include<stack>#include<cctype>#include<cstring>#include<cstdio>#define MAX 50#define MAXNUM 500using namespace std;struct node{struct node* left;struct node* right;char data[MAX];}; typedef struct node* myNode;myNode creatNode(char a[])//传入数组,新建结点{myNode T=new node;T->left =T->right =NULL;strcpy(T->data,a);return T;} char* postExp(char strs[])//将中缀表达式转换成逆波兰表达式 {int i=0;char ch;char c;stack<char> s1;stack<char> s2;s1.push('$');while((ch=strs[i])!='\0'){    if(ch=='(')        s1.push(ch);    if(ch==')'){        while(s1.top()!='('){            s2.push(s1.top());            s1.pop();            }        s1.pop();    }    if(ch=='+'||ch=='-')    {        for(c=s1.top();s1.top()!='('&&s1.top()!='$';)        {            s2.push(s1.top());            s1.pop();        }        s1.push(ch);    }    if(ch=='*'||ch=='/')    {        for(c=s1.top();s1.top()!='('&&s1.top()!='+'&&s1.top()!='-'&&s1.top()!='$';)        {              s2.push(s1.top());              s1.pop();        }        s1.push(ch);    }    if(ch>='0'&&ch<='9')    {           while(ch!='\0'&&ch>='0'&&ch<='9')            {                s2.push(ch);                ch=strs[++i];            }        i--;        s2.push('#');    }    i++;    }for(;s1.top()!='$';){    s2.push(s1.top());    s1.pop();}while(!s2.empty()){    s1.push(s2.top());    s2.pop();}char *tempstr;tempstr=new char[s1.size()+1];int j=0;while(!s1.empty()){    tempstr[j++]=s1.top();    s1.pop();}tempstr[j]='\0';return tempstr;}myNode getTree(char *poststr) //用逆波兰表达式建树{stack<myNode> tempstack;char tempArray [MAX]={0};//数字或者操作符,这里都是用字符形式存的myNode T=NULL;myNode S=NULL;myNode R=NULL;int i=0;int j=0;while(poststr[i]!='$'){    while(isdigit(poststr[i])!=0){        tempArray[j++]=poststr[i++];        if(poststr[i]=='#')        {            tempArray[j]='\0';            T=creatNode(tempArray);            tempstack.push(T);            j=0;            memset(tempArray,0,MAX);            break;        }    }        if(poststr[i]=='+'||poststr[i]=='-'||poststr[i]=='*'||poststr[i]=='/')    {        S=tempstack.top();        tempstack.pop();        T=tempstack.top();        tempstack.pop();        tempArray[0]=poststr[i];        R=creatNode(tempArray);        R->left =T;        R->right =S;        tempstack.push(R);    }    i++;}R=tempstack.top();return R;   }int postOrder(myNode t)//后序遍历 {int num;if(t!=NULL){    if(strcmp(t->data,"+")!=0&&strcmp(t->data,"-")!=0&&strcmp(t->data,"*")!=0&&strcmp(t->data,"/")!=0)        {            num=0;            int i=0;            while(t->data[i]!='\0')            {                num=10*num+t->data[i]-'0';                i++;            }                   }//将字符数组转换成数字    else{        if(strcmp(t->data,"+")==0)            num=postOrder(t->left )+postOrder(t->right );        if(strcmp(t->data,"-")==0)            num=postOrder(t->left )-postOrder(t->right );        if(strcmp(t->data,"/")==0)            num=postOrder(t->left )/postOrder(t->right );        if(strcmp(t->data,"*")==0)            num=postOrder(t->left )*postOrder(t->right );    }    return num;}} int main(){char str[MAXNUM];gets(str);char* str1= postExp(str);cout<<"逆波兰表达式:"<<str1<<endl;cout<<"计算结果是:"<<postOrder(getTree(str1));}

说实话,表达树真叫人脑袋大,竟然写了一个下午!用了STL,要不脑袋更大!!主要思路就是先求逆波兰表达式,然后建一个栈,遇到数字就挂进去,遇到操作符就取出两个,建一个树,再挂回去,最后形成一个大树。
求值的话,就是用后序遍历,稍微改进一下即可。

原创粉丝点击