利用二叉树的遍历解决表达式问题

来源:互联网 发布:2016淘宝秒杀软件app 编辑:程序博客网 时间:2024/06/16 19:46

输入为一个前缀表达式,输出其中辍表达式,并加上括号,然后对其值进行计算,对其中的变量进行赋值,然后计算。

对于输入的表达式,首先要还原二叉树,首先要明白,前缀表达式的获得方式,表达式中是用运算符做结点,然后构建出的二叉树,通过先序遍历的方式获得的,所以根据这一规律,还原出二叉树的状态,然后在对其进行中序遍历得到表达式

const char opr[] = {'+', '-', '*', '/', '^'};
int tree[2*MAXNUM];
int str_loc;

用来判断表达式中出现的运算符

void ReadExpr(int tree_loc) {if (exp[str_loc] == '\n')return;if (tree_loc > MAXN) {MAXN = tree_loc;}int i = 0;int flag = 0;// 判断是否为算术符for (i = 0; i < 5; i++) {if (exp[str_loc] == opr[i]) {flag = 1;break;}}// 建立新结点tree[tree_loc] = exp[str_loc];str_loc++;// 遍历子树if (flag) { ReadExpr(2 * tree_loc);ReadExpr(2 * tree_loc + 1); }}
首先判断输入的表达式是否为换行,也就是结束了,如果结束,跳出该方法,然后判断当前传入的字符是否为算术运算符,如果是的话,就将该位放入到数组中,然后字符数组向下移动一位,然后对其左右子树进行遍历,递归调用该方法,也就是将后面的每一个结点重新当做一个新的结点进行判断,这样就将原来二叉树以数组的形式进行了存放。

然后对其进行中序遍历,也就是先遍历左子树然后遍历根节点,最后遍历右子树。

// 用带括弧的中缀表达式输出,本质为中序遍历二叉树void WriteExpr(int tree_loc) {// 遍历左子树并加入括号if (tree_loc * 2 <= MAXN && tree[tree_loc * 2] != 0) {printf("(");WriteExpr(tree_loc * 2);printf(")");}// 遍历根结点printf("%c", tree[tree_loc]);// 遍历右子树并加上括号if (tree_loc * 2 + 1 <= MAXN && tree[tree_loc * 2 + 1] != 0) {printf("(");WriteExpr(tree_loc * 2 + 1);printf(")");}}
对于递归函数的问题,程序写起来简洁明了,但是对于其执行过程还是比较难理解的,通过画工作栈的方式来理解一下这个问题,没解决一层就将该层出栈。

然后对我们输入的表达式进行求值,通过后序遍历的方式来进行求得最后的答案,

int key_value[26];

int Value(int tree_loc) {int a, b;if (tree[tree_loc] >= 'a' && tree[tree_loc] <= 'z') {return key_value[tree[tree_loc] - 'a'];}if (tree[tree_loc] >= '0' && tree[tree_loc] <= '9') {return tree[tree_loc] - '0';}// 遍历左子树if (tree_loc * 2 <= MAXN && tree[tree_loc] != 0) { a = Value(tree_loc * 2);}// 遍历右子树if (tree_loc * 2 + 1 <= MAXN && tree[tree_loc] != 0) {b = Value(tree_loc *  2 + 1);}switch(tree[tree_loc]) {case '+': return a + b; break;case '-': return a - b; break;case '*': return a * b; break;case '/': return a / b; break;case '^': return pow(a, b); break;}}
在tree数组中存放的是字符串的编码,所以首先要通过相应的计算得到其实际的值,然后对其进行左右遍历。






0 0
原创粉丝点击