7:表达式·表达式树·表达式求值
-
总时间限制:
- 1000ms 内存限制:
- 65535kB
-
描述
-
众所周知,任何一个表达式,都可以用一棵表达式树来表示。例如,表达式a+b*c,可以表示为如下的表达式树:
+
/ \
a *
/ \
b c现在,给你一个中缀表达式,这个中缀表达式用变量来表示(不含数字),请你将这个中缀表达式用表达式二叉树的形式输出出来。
输入
-
输入分为三个部分。
第一部分为一行,即中缀表达式(长度不大于50)。中缀表达式可能含有小写字母代表变量(a-z),也可能含有运算符(+、-、*、/、小括号),不含有数字,也不含有空格。
第二部分为一个整数n(n < 10),表示中缀表达式的变量数。
第三部分有n行,每行格式为C x,C为变量的字符,x为该变量的值。
输出
-
输出分为三个部分,第一个部分为该表达式的逆波兰式,即该表达式树的后根遍历结果。占一行。
第二部分为表达式树的显示,如样例输出所示。如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠(\)来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,\出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。
第三部分为一个整数,表示将值代入变量之后,该中缀表达式的值。需要注意的一点是,除法代表整除运算,即舍弃小数点后的部分。同时,测试数据保证不会出现除以0的现象。
样例输入
-
a+b*c 3 a 2 b 7 c 5
样例输出
-
abc*+ + / \ a * / \ b c 37
#include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<iomanip> #include<queue> #include<stack> #include<vector> #include<set> #include<map> using namespace std; char pro[55]; char buf[105][305]; struct Node { char c; Node*l; Node*r; Node(char cc) { c=cc;l=NULL;r=NULL; } }; int CountLayer(Node*root) { if(root==NULL)return 0; int L=CountLayer(root->l); int R=CountLayer(root->r); if(L>=R)return L+1; else return R+1; } void MakeTree(Node*root,int x,int y,int wide) { if(root==NULL)return; buf[y][x-1]=root->c; if(root->l!=NULL) { buf[y+1][x-2]='/'; MakeTree(root->l,x-wide,y+2,wide>>1); } if(root->r!=NULL) { buf[y+1][x]='\\'; MakeTree(root->r,x+wide,y+2,wide>>1); } } int main() { //输出逆波兰表达式 string s; cin>>s; int len=s.length(); int cur=0; stack<char>S; for(int i=0;i<len;++i) { if(s[i]>='a'&&s[i]<='z') { pro[cur++]=s[i]; } else if(s[i]=='(') { S.push(s[i]); } else if(s[i]==')') { while(S.top()!='(') { pro[cur++]=S.top(); S.pop(); } S.pop(); } else if(s[i]=='+'||s[i]=='-') { while(!S.empty()&&S.top()!='(') { pro[cur++]=S.top(); S.pop(); } S.push(s[i]); } else if(s[i]=='*'||s[i]=='/') { while(!S.empty()&&(S.top()=='*'||S.top()=='/')) { pro[cur++]=S.top(); S.pop(); } S.push(s[i]); } } while(!S.empty()) { pro[cur++]=S.top(); S.pop(); } pro[cur]=0; cout<<pro<<endl; //输出表达式树 Node*root; stack<Node*>S1; for(int i=0;i<cur;++i) { root=new Node(pro[i]); if(pro[i]<'a'||pro[i]>'z') { root->r=S1.top(); S1.pop(); root->l=S1.top(); S1.pop(); } S1.push(root); } memset(buf,' ',sizeof(buf)); int Layer=CountLayer(root); MakeTree(root,1<<(Layer-1),0,1<<(Layer-2)); for(int i=0;i<((Layer<<1)-1);++i) { int j=300; while(j>0&&buf[i][j]==' ') j--; buf[i][j+1]=0; } for(int i=0;i<((Layer<<1)-1);++i) { cout<<buf[i]<<endl; } //输出表达式的值 int n,a; char c; stack<int>T; map<char,int>M; cin>>n; for(int i=0;i<n;++i) { cin>>c>>a; M[c]=a; } for(int i=0;i<cur;++i) { if(pro[i]>='a'&pro[i]<='z') { T.push(M[pro[i]]); continue; } int tmp1=T.top();T.pop(); int tmp2=T.top();T.pop(); if(pro[i]=='+') { T.push(tmp2+tmp1); } else if(pro[i]=='-') { T.push(tmp2-tmp1); } else if(pro[i]=='*') { T.push(tmp2*tmp1); } else if(pro[i]=='/') { T.push(tmp2/tmp1); } } cout<<T.top()<<endl; return 0; }