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


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


  • 相关阅读:
    PHP学习笔记
    《疯狂Kotlin讲义》读书笔记6——函数和Lambda表达式
    《疯狂Kotlin讲义》读书笔记5——数组和集合
    《疯狂Kotlin讲义》读书笔记4——流程控制
    《疯狂Kotlin讲义》读书笔记3——运算符与表达式
    《疯狂Kotlin讲义》读书笔记2——Kotlin的基本类型
    浅谈Android中的事件分发机制
    Android:自定义View之番茄钟
    十年老苹果(A1286)强升Catalina及Win10踩坑记(续)
    Python系列(7)——使用openpyxl写银行系统
  • 原文地址:https://www.cnblogs.com/Jstyle-continue/p/6351960.html
Copyright © 2020-2023  润新知