算法竞赛入门经典第11章 表达式树

题目:给出一个由数字及’+’,’-’,‘x’,’/’ 以及括号组成的合法算式,将其转化为表达式树。
表达式树的所有树叶都是操作数,非叶子节点都是运算符。由于给出的运算符都是二元运算符,因此这道题得到的树一定是二叉树。可以先寻找“最后计算的运算符”,将这个运算符作为一个结点,然后递归计算运算符左右两个算式,计算结果作为该节点的左右儿子。

直接上代码,需要注意的问题都写在注释里。

#include<iostream>
#include<vector>
#include<string>
#include<iomanip>

using namespace std;

string input;

struct Node //定义树的结点类型
{
    int num;
    char op; //每个节点要么是整型(操作数),要么是字符型(运算符)
    Node* left = nullptr;
    Node* right = nullptr;
};

Node* build_tree (int x, int y) //将[x,y]部分运算式转化成表达式树,并返回根
{
    int p = 0; int c1 = -1; int c2 = -1; //p记录括号情况, c1记录括号外最后一个加号或者减号位置, c2记录括号外最后一个乘号或者除号位置
    Node* root = new Node; //root将会保存找到的最后一个计算的运算符
    for(int i = x; i <= y; i++)
    {
        switch(input[i]) 
        {
            case '(': p++; break;
            case ')': p--; break;
            case '+': case '-': if(!p) c1 = i; break; //p增加过和减少过次数一样或p没有改变过,表示在括号外,保存运算符
            case '*': case '/': if(!p) c2 = i; break; 
        } 
    }
    if(c1 < 0) c1 = c2; //没有找到加号减号,使用乘号或除号
    if(c1 < 0) //括号外的运算符都没有,分两种情况:
    {
        if(input[x] == '(') return build_tree (x+1, y-1); //1.整个式子被括号括起来,去掉括号重新计算
        int cur_num = 0; //2.[x,y]范围内是一个完整数字(可能是一位数也可能是多位数,如123, 需要转化成int类型并保存到cur_num
        while(x <= y) 
        {
            cur_num *= 10;
            cur_num += input[x++]-'0';
        }
        root -> num = cur_num;
        return root;
    }
    root -> op = input[c1];
    root -> left = build_tree (x, c1 - 1); //递归计算左侧表达式
    root -> right = build_tree (c1 + 1, y); //递归计算右侧表达式
    return root;
}


void print_tree (Node* root, int indent) //indent表示缩进空格数目,每个节点比它的儿子节点少缩进4个空格。Inorder。
{
    if (root == nullptr) return;
    print_tree (root -> left, indent + 4);
    if (root -> num != -1) cout << setw(indent) <<' '<< root -> num; //setw函数保存在头文件<iomanip>里
        else cout << setw(indent) <<' '<< root -> op;
        cout<<endl;
    print_tree (root -> right, indent + 4);
}

int main ()
{	
	cin>>input;
    int n = input.size();
    Node* root = build_tree (0, n - 1); //注意build_tree(x, y)的两个参数表示闭区间[x,y]
    print_tree (root, 0);
    return 0;
}

输入"1+(2+3) * 4"
结果:
在这里插入图片描述
输入"12-(1+5) * 6+500/(2+3)-4 * 5 * 6"
结果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值