表达式树(图论) By ACReaper

形如6*(2+3)+9计算其值,要是在面向对象的语言中,用脱窗口的方法是很好解决的,是不。不过我们要写的是算法。

思想:

通过观察表达式我们可以发现一个规律,就是我们可以先找到最后运算的符号,然后计算其左边,其右边,接着把它连接如符号计算。这个思想和简单,也很容易理解,其实这个思想所建立的树也就是后缀树。


代码实现如下:


#include <stdio.h>
#include <string.h>
const int maxn = 1000;
int lch[maxn], rch[maxn];
char op[maxn];
char input[maxn];
int nc = 0;
int build_tree(char *s,int x,int y){
	int i,c1 = -1,c2 = -1,p =0;//p用来标记是否在括号内
	int u;
	if(y - x == 0){//当只有一个字符,也就是叶子结点,则,生成叶子结点,存入
		u = ++nc;
		lch[u] = rch[u] = 0;
		op[u] = s[x];
		return u;
	}
	for(i = x; i <= y; i++){
		switch(s[i]){
			case '(':p++;break;//进入括号内加加
			case ')':p--;break;//出括号渐减
			case '+':case '-':if(!p) c1 = i;break;
			case '*':case '/':if(!p) c2 = i;break;
		}
	}
	if(c1 < 0) c1 = c2;
	if(c1 < 0) return build_tree(s,x + 1,y - 1);
	u = ++nc;
	lch[u] = build_tree(s,x,c1 - 1);
	rch[u] = build_tree(s,c1 + 1,y);
	op[u] = s[c1];
	return u;
} 
int count_value(int root){
	if(lch[root] == rch[root] && lch[root] == 0){
		return op[root] - '0';	
	}else{
		switch(op[root]){
			case '+':return count_value(lch[root]) + count_value(rch[root]);
			case '-':return count_value(lch[root]) - count_value(rch[root]);
			case '*':return count_value(lch[root]) * count_value(rch[root]);
			case '/':return count_value(lch[root]) / count_value(rch[root]);
		}
	}
}
int main(){
	while(scanf("%s",input) != EOF){
		memset(lch,0,sizeof(lch));
		memset(rch,0,sizeof(rch));
		int len = strlen(input);
		int root = build_tree(input,0,len - 1);
		printf("%d\n",count_value(root));
	}
	return 0;
}


posted @ 2013-04-23 10:58  算法黑魔王  阅读(213)  评论(0编辑  收藏  举报