你们要的中缀表达式树

389 篇文章 1 订阅
8 篇文章 0 订阅

你们要的中缀表达式树
Case Time Limit: 100 MS (Others) / 200 MS (Java) Case Memory Limit: 256 MB (Others) / 512 MB (Java)
Accepted: 32 Total Submission: 141
查看我的提交显示标签
Problem Description
给定一棵二叉树,二叉树的各个结点要么表示四则运算符+、-、*、/,要么表示一个不超过10的非负整数。将这棵二叉树看作中缀表达式树,输出对应的中缀表达式,以及该中缀表达式的计算结果。
注意,输出的中缀表达式中,除了最外层以外,内层的每个“左操作数 操作符 右操作数”形式的两侧都要加上一对小括号。例如2+(3*(4/5))就是一个可能的正确输出。
Input
每个输入文件中一组数据。
第一行一个正整数N(N<=30),代表二叉树的结点个数(结点编号为0到N-1)。
第二行按结点编号从小到大的顺序给出N个结点的值(用空格隔开),其要么是四则运算符+、-、*、/的其中一个,要么是一个不超过10的非负整数。
接下来按结点编号从小到大的顺序给出N行,每行为两个编号,分别代表该结点的左孩子编号和右孩子编号,如果不存在左(右)孩子,那么就用字符’-‘代替。数据保证编号在0到N-1之间,且中缀表达式树一定是合法的。
Output
输出一行,即所求的中缀表达式与对应的计算结果(精度保留两位小数),表达式与计算结果之间用空格隔开。注意输出的中缀表达式中不允许有空格。数据保证中缀表达式合法,且计算过程中不会出现除数为0的情况。
Sample Input
5
* 3 + 4 6
1 2
- -
3 4
- -
- -
Sample Output
3*(4+6) 30.00
Author
Shoutmon
Source
17浙大考研机试模拟赛

思路,中缀表达式很好球,建树后直接中序遍历即可,然后去掉最外层括号,用string很容易实现,难点在于求值,因为题目中数值大于等于0小于等于10,所以可能出现两位,因此可以用char存储数值和计算符号,本次实现借助了flag来判断是否为运算符,因此代码比较多,可以将数值也存到char中, 这里不做阐述

#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <string>
using namespace std;
const int MaxN = 36;
int N;
struct node {
    int data;
    bool sign;
    char s;
    int lchild;
    int rchild;
    node() { rchild = lchild = -1; sign = false; }
}Node[MaxN];

bool isRoot[MaxN];
string res;

string IntToStr(int num) {
    string str;
    while (num) {
        str.insert(str.begin(),num % 10 + '0');
        num /= 10;
    }
    if (!str.size()) return "0";
    return str;
}

double post(int root) {
    if (-1 == root) return 0;
    bool flag = (Node[root].lchild != -1 || Node[root].rchild != -1);
    if (flag) res += "(";

    double leftv = post(Node[root].lchild);
    if (Node[root].sign) res += Node[root].s;
    else res += IntToStr(Node[root].data);

    double rightv = post(Node[root].rchild);

    if (flag) res += ")";

    if (!Node[root].sign) return Node[root].data;
    else {
        switch (Node[root].s)
        {
        case '+':return leftv + rightv;
        case '-':return leftv - rightv;
        case '*':return leftv * rightv;
        case '/':return leftv / rightv;
        default:
            return 0;
        }
    }
}


int main() {
#ifdef _DEBUG
    freopen("data.txt", "r+", stdin);
#endif // _DEBUG
    std::ios::sync_with_stdio(false);

    stringstream ss; string str; int idx = 0;
    cin >> N; cin.get(); getline(cin, str); ss << str;
    for (int i = 0; i < N; ++i) {
        if ('0' <= str[idx] && str[i] <= '9') {
            ss >> Node[i].data;
        }
        else {
            char ch;
            ss >> ch;
            Node[i].s = ch;
            Node[i].sign = true;
        }
        while (idx < str.size()-1 && str[idx] != ' ')++idx;
        if (idx < str.size() - 1) ++idx;
    }
    memset(isRoot, 1, N + 1);
    for (int i = 0; i < N; ++i) {
        ss.clear(); ss.str("");
        getline(cin, str); ss << str;
        int idx = 0, lc, rc;
        if (str[idx] == '-') {
            ss.get();
            ++idx;
        }
        else {
            ss >> Node[i].lchild;
            isRoot[Node[i].lchild] = false;
        }

        while (str[idx] != ' ')++idx;
        ++idx;

        if (str[idx] != '-') {
            ss >> Node[i].rchild;
            isRoot[Node[i].rchild] = false;
        }
    }

    int root = 0;
    while (!isRoot[root])++root;

    double val = post(root);

    if (res.size() >= 3) {
        res.erase(res.begin());
        res.erase(res.end()-1);
    }
    cout << res << " " ;
    cout << setiosflags(ios::fixed) << setprecision(2) << val;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值