表达式树 (二叉树的应用)

#include <iostream>
#include <string>
#include <cstring>
#define MAX 1005

using namespace std;
/*************************************************************************************************************
        表达式树:将一个四则运算表达式(含括号)转化成二叉树并计算结果
        创建树(递归):
        1,找到“最后运算”的运算符(一定为树的根),然后递归创建
        2,利用 p == 0 时找到最右出现的 + - 和 * / 运算符,分别用 c1 c2保存位置
           p != 0时该操作符一定在括号内,且括号一定不是最后计算,只有 p == 0才考虑当前字符
        3,当 c1 < 0时,说明没有 + - 操作符出现在最右,则需考虑 * /运算符。(c1 = c2)
           若 c2 也小于 0,说明整个算式最右无 + - * /,即整个算式都在一个大括号内
           去掉括号递归调用即可 build_tree(x+1,y-1);
        4,递归创建左右子树即可
        5,计算表达式的结果,递归遍历树即可,碰到叶子结点即非操作符结点 return 即可;
        Input:
            a+b
            a+b*(f-a)-d/b
            (a+b*c)
        OutPut:
            3
            9
            7

        PS:这里写的是一个一般化的程序,如果输入数字,将字母改成数字即可
*************************************************************************************************************/
string s;
int nc;     //结点编号
int lch[MAX],rch[MAX];	//左右孩子结点编号
char op[MAX];		//结点的操作字符
int ans = 0;		//计算结果

int build_tree(int x,int y){
	int c1 = -1,c2 = -1,p = 0;
	int u;		//结点编号
	if(y-x == 1){
		u = ++nc;
		lch[u] = rch[u] = 0;
		op[u] = s[x];
		return u;
	}
	for(int i = x;i < y;i ++){
		if(s[i] == '(')	p++;
		if(s[i] == ')')	p--;
		if(!p && (s[i] == '+' || s[i] == '-'))
			c1 = i;
		if(!p && (s[i] == '*' || s[i] == '/'))
			c2 = i;
	}

	if(c1 < 0 && c2 < 0)		//找不到最后出现的四则运算符号,即整个算式被大括号括着
		return build_tree(x+1,y-1);
	if(c1 < 0)		//找不到 + || - 运算,就用 * || / 运算
		c1 = c2;

	u = ++nc;
	lch[u] = build_tree(x,c1);
	rch[u] = build_tree(c1+1,y);
	op[u] = s[c1];
	return u;
}

int dfs(int id){
	if(isalpha(op[id]))	return (int)(op[id]-'a' + 1);

	if(op[id] == '+')
        return dfs(lch[id]) + dfs(rch[id]);
	if(op[id] == '-')
        return dfs(lch[id]) - dfs(rch[id]);
	if(op[id] == '*')
        return dfs(lch[id]) * dfs(rch[id]);
	if(op[id] == '/')
        return dfs(lch[id]) / dfs(rch[id]);
}
int main()
{
	while(cin>>s){
        nc = 0;     //每次重置结点编号从0开始

		int len = s.size();
		build_tree(0,len);
		/*for(int i = 1;i <= nc;i ++)       //可利用输出查看树的构建情况,包括根节点,左右孩子结点
			cout<<"op: "<<op[i]<<"  lch: "<<lch[i]<<"  rch: "<<rch[i]<<endl;*/
        ans = dfs(1);
        cout<<ans<<endl;
	}
	return 0;
}


posted on 2016-05-25 12:00  Jstyle  阅读(185)  评论(0编辑  收藏  举报

导航