表达式·表达式树·表达式求值

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;
    }
    


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值