Expression Expression tree Expression evaluation
題目地址
http://dsalgo.openjudge.cn/binarytree/7/
題目大意
表示式·表示式樹·表示式求值
描述
眾所周知,任何一個表示式,都可以用一棵表示式樹來表示。例如,表示式a+b*c,可以表示為如下的表示式樹:
+
/ \
a *
/ \
b c
現在,給你一箇中綴表示式,這個中綴表示式用變數來表示(不含數字),請你將這個中綴表示式用表示式二叉樹的形式輸出出來。
輸入
輸入分為三個部分。
第一部分為一行,即中綴表示式(長度不大於50)。中綴表示式可能含有小寫字母代表變數(a-z),也可能含有運算子(+、-、*、/、小括號),不含有數字,也不含有空格。
第二部分為一個整數n(n < 10),表示中綴表示式的變數數。
第三部分有n行,每行格式為C x,C為變數的字元,x為該變數的值。
輸出
輸出分為三個部分,第一個部分為該表示式的逆波蘭式,即該表示式樹的後根遍歷結果。佔一行。
第二部分為表示式樹的顯示,如樣例輸出所示。如果該二叉樹是一棵滿二叉樹,則最底部的葉子結點,分別佔據橫座標的第1、3、5、7……個位置(最左邊的座標是1),然後它們的父結點的橫座標,在兩個子結點的中間。如果不是滿二叉樹,則沒有結點的地方,用空格填充(但請略去所有的行末空格)。每一行父結點與子結點中隔開一行,用斜槓(/)與反斜槓(\)來表示樹的關係。/出現的橫座標位置為父結點的橫座標偏左一格,\出現的橫座標位置為父結點的橫座標偏右一格。也就是說,如果樹高為m,則輸出就有2m-1行。
第三部分為一個整數,表示將值代入變數之後,該中綴表示式的值。需要注意的一點是,除法代表整除運算,即捨棄小數點後的部分。同時,測試資料保證不會出現除以0的現象。
樣例輸入
a+b*c
3
a 2
b 7
c 5
樣例輸出
abc*+
+
/ \
a *
/ \
b c
37
Code
#include <iostream>
#include <stack>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <algorithm>
#define INF 0x3fffffff
#define MAXROW 70
#define MAXCOL 300
using namespace std;
int layers;
char bl[128];
char buf[512 ][512];
map<char, int> mci;
struct Node {
char v;
Node* l;
Node* r;
Node() {
l = NULL;
r = NULL;
}
Node(char c) {
v = c;
l = NULL;
r = NULL;
}
};
void get_bl(string s) {
memset(bl, 0, sizeof(bl));
int j = 0;
stack<char > sc;
for (int i = 0; i < s.size(); i++) {
if (isalpha(s[i])) {
bl[j++] = s[i];
} else if (s[i] == '(') {
sc.push(s[i]);
} else if (s[i] == ')') {
while ((!sc.empty()) && (sc.top() != '(')) {
bl[j++] = sc.top();
sc.pop();
}
sc.pop();
} else if (s[i] == '+' || s[i] == '-') {
while ((!sc.empty()) && (sc.top() != '(')) {
bl[j++] = sc.top();
sc.pop();
}
sc.push(s[i]);
} else {
while ((!sc.empty()) && (sc.top() == '*' || sc.top() == '/')) {
bl[j++] = sc.top();
sc.pop();
}
sc.push(s[i]);
}
}
while (!sc.empty()) {
bl[j++] = sc.top();
sc.pop();
}
bl[j] = '\0';
}
Node* build_tree() {
stack<Node*> sn;
for (int i = 0; i < strlen(bl); i++) {
if (isalpha(bl[i])) {
Node* node = new Node(bl[i]);
sn.push(node);
} else {
Node* node = new Node(bl[i]);
node->r = sn.top(); sn.pop();
node->l = sn.top(); sn.pop();
sn.push(node);
}
}
return sn.top();
}
int calculate(Node* root){
if (isalpha(root->v)) return mci[root->v];
if (root->v=='+') return calculate(root->l)+calculate(root->r);
if (root->v=='-') return calculate(root->l)-calculate(root->r);
if (root->v=='*') return calculate(root->l)*calculate(root->r);
if (root->v=='/') return calculate(root->l)/calculate(root->r);
}
int cal(int a, int b, char c) {
switch (c) {
case '+': return a+b; break;
case '-': return a-b; break;
case '*': return a*b; break;
case '/': return a/b; break;
}
}
void calculate2() {
// cal2
stack<int> si;
for (int i = 0; i < strlen(bl); i++) {
if (isalpha(bl[i])) {
si.push(mci[bl[i]]);
} else {
int x = si.top(); si.pop();
int y = si.top(); si.pop();
int z = cal(y, x, bl[i]);
si.push(z);
}
}
cout << si.top();
}
int get_layer(Node *root) {
if (root == NULL) {
return 0;
}
int left = get_layer(root->l);
int right = get_layer(root->r);
return max(left+1, right+1);
}
void print_tree(Node * root, int root_x, int root_y, int space){
int left_child, right_child;
if (!root) return;
buf[root_y][root_x-1] = root->v;
if (root->l){
buf[root_y+1][root_x-2] = '/';
print_tree(root->l,root_x-space,root_y+2,space>>1);
}
if (root->r){
buf[root_y+1][root_x] = '\\';
print_tree(root->r,root_x+space,root_y+2,space>>1);
}
}
void print(Node* root) {
layers = get_layer(root);
memset(buf, ' ', sizeof(buf));
int b = INF;
print_tree(root, pow(2,layers-1), 0, pow(2,layers-2));
for (int i = 0; i < 2*layers-1; i++) {
for (int j = 300; j >= 0; j--) {
if (buf[i][j] != ' ') {
buf[i][j+1] = '\0';
break;
}
}
}
for (int i = 0; i < 2*layers-1; i++) {
printf("%s\n", buf[i]);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
string s;
int n;
char c;
int v;
cin >> s;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> c >> v;
mci[c] = v;
}
get_bl(s);
printf("%s\n", bl);
Node *root = build_tree();
print(root);
int ans = calculate(root);
//cout << ans << endl;
calculate2();
return 0;
}