中缀表达式树及其结果计算

题目

给定一棵二叉树,二叉树的各个结点要么表示四则运算符+、-、*、/,要么表示一个不超过10的非负整数。将这棵二叉树看作中缀表达式树,输出对应的中缀表达式,以及该中缀表达式的计算结果。
注意,输出的中缀表达式中,除了最外层以外,内层的每个“左操作数 操作符 右操作数”形式的两侧都要加上一对小括号。例如2+(3*(4/5))就是一个可能的正确输出。


输入

每个输入文件中一组数据。
第一行一个正整数N(N<=30),代表二叉树的结点个数(结点编号为0到N-1)。
第二行按结点编号从小到大的顺序给出N个结点的值(用空格隔开),其要么是四则运算符+、-、*、/的其中一个,要么是一个不超过10的非负整数。
接下来按结点编号从小到大的顺序给出N行,每行为两个编号,分别代表该结点的左孩子编号和右孩子编号,如果不存在左(右)孩子,那么就用字符'-'代替。数据保证编号在0到N-1之间,且中缀表达式树一定是合法的。


输出

输出一行,即所求的中缀表达式与对应的计算结果(精度保留两位小数),表达式与计算结果之间用空格隔开。注意输出的中缀表达式中不允许有空格。数据保证中缀表达式合法,且计算过程中不会出现除数为0的情况。


输入样例

5

* 3 + 4 6

1 2

- -

3 4

- -

- -


输出样例

3*(4+6) 30.00


标程

#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
using namespace std;
const int MAX = 30;
struct node{  //树结点
	string data;
	int lchild, rchild;
}Node[MAX];
int n;
bool isroot[MAX];

void create(){ //构造二叉树
	cin >> n;
	for (int i = 0; i < n; i++){
		cin >> Node[i].data;
	}
	string str;
	for (int i = 0; i < n; i++){
		cin >> str;
		if (str == "-"){ //左孩子为空
			Node[i].lchild = -1;
		}
		else{
			if (str.length() == 1){  //一位数
				Node[i].lchild = str[0] - '0';
				isroot[Node[i].lchild] = false;  //左孩子为非根结点
			}
			else{  //两位数
				Node[i].lchild = (str[0] - '0') * 10 + (str[1] - '0');
				isroot[Node[i].lchild] = false;  //左孩子为非根结点
			}
		}
		cin >> str;
		if (str == "-"){  //右孩子为空
			Node[i].rchild = -1;
		}
		else{
			if (str.length() == 1){//一位数
				Node[i].rchild = str[0] - '0';
				isroot[Node[i].rchild] = false; //右孩子非根
			}
			else{  //两位数
				Node[i].rchild = (str[0] - '0') * 10 + (str[1] - '0');
				isroot[Node[i].rchild] = false;  //右孩子非根
			}
		}
	}
}

int findroot(){  //找到根结点
	for (int i = 0; i < n; i++){
		if (isroot[i])
			return i;
	}
}

void inorder(int root){   //中序遍历并输出表达式
	if (!(Node[root].data == "+" || Node[root].data == "-" || Node[root].data == "*" || Node[root].data == "/")){
		cout << Node[root].data;
	}
	else{
		cout << "(";  
		inorder(Node[root].lchild);   //对左子树递归
		cout << Node[root].data;
		inorder(Node[root].rchild);  //对右子树递归
		cout << ")";
	}
}

double cal(int root){    //计算某个节点的表达式值
	if (!(Node[root].data == "+" || Node[root].data == "-" || Node[root].data == "*" || Node[root].data == "/")){ //数值结点即为根
		if (Node[root].data.length() == 1)  //返回数值
			return Node[root].data[0] - '0';
		else if (Node[root].data.length() == 2)
			return (Node[root].data[0] - '0') * 10 + (Node[root].data[1] - '0');
	}
	else if (Node[root].data == "+")return cal(Node[root].lchild) + cal(Node[root].rchild);  //用左子树的结果和右子树结果计算
	else if (Node[root].data == "-")return cal(Node[root].lchild) - cal(Node[root].rchild);
	else if (Node[root].data == "*")return cal(Node[root].lchild) * cal(Node[root].rchild);
	else if (Node[root].data == "/")return cal(Node[root].lchild) / cal(Node[root].rchild);
}

int main(){
	fill(isroot, isroot + MAX, true);  //初始化根标志数组
	create();  //构造树
	int root = findroot();  //找到根
	inorder(Node[root].lchild);  //因最外层无括号单独处理根结点
	cout << Node[root].data;
	inorder(Node[root].rchild);
	printf(" ");
	printf("%.2f", cal(root));  //对根计算并输出
	cin >> n;  //调试用观察输出
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值