|
|
#include <bits/stdc++.h>
|
|
|
|
|
|
using namespace std;
|
|
|
/**
|
|
|
从后缀表达式建立表达式树
|
|
|
比如现在有以下一个后缀表达式:
|
|
|
a b + c d e + * *
|
|
|
根据这个后缀表达式建立二叉表达式树,算法如下:
|
|
|
1. 依次读取表达式;
|
|
|
2. 如果是操作数,则将该操作数压入栈中;
|
|
|
3. 如果是操作符,则弹出栈中的两个操作数,第一个弹出的操作数作为右孩子,第二个弹出的操作数作为左孩子;然后再将该操作符压入栈中。
|
|
|
这样下去,就可以建立一颗完整的表达式树。
|
|
|
*/
|
|
|
// https://www.cnblogs.com/Running-Time/p/4922670.html
|
|
|
typedef long long LL;
|
|
|
const int N = 1e5 + 10;
|
|
|
const int INF = 0x3f3f3f3f;
|
|
|
const int MOD = 1e9 + 7;
|
|
|
|
|
|
/*
|
|
|
表达式求值,逆波兰式(后缀表达式)算法
|
|
|
输入(可以有空格,支持小数,实现'+-/*%'): ((1+2)*5+1)/4=
|
|
|
注意:取模一定是要整型,实现版本数字全是double,强制类型转换可能倒置错误
|
|
|
转换为后缀表达式: 得到:1 2 + 5 * 1 + 4 / =
|
|
|
计算后缀表达式:得到:4.00
|
|
|
*/
|
|
|
bool is_digit(char ch) {
|
|
|
return '0' <= ch && ch <= '9';
|
|
|
}
|
|
|
|
|
|
struct Exp {
|
|
|
stack<char> op;
|
|
|
stack<double> num;
|
|
|
|
|
|
int prior(char ch) { //运算符的优先级
|
|
|
switch (ch) {
|
|
|
case '+':
|
|
|
case '-':
|
|
|
return 1;
|
|
|
case '*':
|
|
|
case '%':
|
|
|
case '/':
|
|
|
return 2;
|
|
|
default:
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
//中缀表达式转变前缀表达式
|
|
|
string get_prefix(string s) {
|
|
|
while (!op.empty()) op.pop();
|
|
|
op.push('#');
|
|
|
string ret = "";
|
|
|
int len = s.length(), i = len - 1;
|
|
|
while (i >= 0) {
|
|
|
if (s[i] == ' ' || s[i] == '=') {
|
|
|
i--;
|
|
|
continue;
|
|
|
} else if (s[i] == ')') {
|
|
|
op.push(s[i--]);
|
|
|
} else if (s[i] == '(') {
|
|
|
while (op.top() != '#' && op.top() != ')') {
|
|
|
ret += op.top();
|
|
|
ret += ' ';
|
|
|
op.pop();
|
|
|
}
|
|
|
op.pop();
|
|
|
i--;
|
|
|
} else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/' || s[i] == '%') {
|
|
|
while (prior(op.top()) > prior(s[i])) {
|
|
|
ret += op.top();
|
|
|
ret += ' ';
|
|
|
op.pop();
|
|
|
}
|
|
|
op.push(s[i--]);
|
|
|
} else {
|
|
|
while (is_digit(s[i]) || s[i] == '.') {
|
|
|
ret += s[i--];
|
|
|
}
|
|
|
ret += ' ';
|
|
|
}
|
|
|
}
|
|
|
while (op.top() != '#') {
|
|
|
ret += op.top();
|
|
|
ret += ' ';
|
|
|
op.pop();
|
|
|
}
|
|
|
reverse(ret.begin(), ret.end());
|
|
|
return ret;
|
|
|
}
|
|
|
//计算
|
|
|
double cal(double a, double b, char ch) {
|
|
|
if (ch == '+') return a + b;
|
|
|
if (ch == '-') return a - b;
|
|
|
if (ch == '*') return a * b;
|
|
|
if (ch == '%') return (int) ((int) a % (int) b);
|
|
|
if (ch == '/') {
|
|
|
if (b != 0) return a / b;
|
|
|
return 0;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
//中缀表达式转变后缀表达式
|
|
|
string get_postfix(string s) {
|
|
|
while (!op.empty()) op.pop();
|
|
|
op.push('#');
|
|
|
string ret = "";
|
|
|
int len = s.length(), i = 0;
|
|
|
while (i < len) {
|
|
|
if (s[i] == ' ' || s[i] == '=') {
|
|
|
i++;
|
|
|
continue;
|
|
|
} else if (s[i] == '(') {
|
|
|
op.push(s[i++]);
|
|
|
} else if (s[i] == ')') {
|
|
|
while (op.top() != '(') {
|
|
|
ret += op.top();
|
|
|
ret += ' ';
|
|
|
op.pop();
|
|
|
}
|
|
|
op.pop();
|
|
|
i++;
|
|
|
} else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/' || s[i] == '%') {
|
|
|
while (prior(op.top()) >= prior(s[i])) {
|
|
|
ret += op.top();
|
|
|
ret += ' ';
|
|
|
op.pop();
|
|
|
}
|
|
|
op.push(s[i++]);
|
|
|
} else {
|
|
|
while (is_digit(s[i]) || s[i] == '.') {
|
|
|
ret += s[i++];
|
|
|
}
|
|
|
ret += ' ';
|
|
|
}
|
|
|
}
|
|
|
while (op.top() != '#') {
|
|
|
ret += op.top();
|
|
|
ret += ' ';
|
|
|
op.pop();
|
|
|
}
|
|
|
ret += '=';
|
|
|
return ret;
|
|
|
}
|
|
|
//计算后缀表达式
|
|
|
double solve(string str) {
|
|
|
string s = get_postfix(str);
|
|
|
while (!num.empty()) num.pop();
|
|
|
int len = s.length(), i = 0;
|
|
|
while (i < len) {
|
|
|
if (s[i] == ' ' || s[i] == '=') {
|
|
|
i++;
|
|
|
continue;
|
|
|
} else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/' || s[i] == '%') {
|
|
|
double a = num.top();
|
|
|
num.pop();
|
|
|
double b = num.top();
|
|
|
num.pop();
|
|
|
num.push(cal(b, a, s[i]));
|
|
|
i++;
|
|
|
} else {
|
|
|
double x = 0;
|
|
|
while (is_digit(s[i])) {
|
|
|
x = x * 10 + s[i] - '0';
|
|
|
i++;
|
|
|
}
|
|
|
if (s[i] == '.') {
|
|
|
double k = 10.0, y = 0;
|
|
|
i++;
|
|
|
while (is_digit(s[i])) {
|
|
|
y += ((s[i] - '0') / k);
|
|
|
i++;
|
|
|
k *= 10;
|
|
|
}
|
|
|
x += y;
|
|
|
}
|
|
|
num.push(x);
|
|
|
}
|
|
|
}
|
|
|
return num.top();
|
|
|
}
|
|
|
} E;
|
|
|
|
|
|
typedef struct BT {
|
|
|
char op;
|
|
|
double data;
|
|
|
BT *lch, *rch;
|
|
|
} node, *btree;
|
|
|
|
|
|
void print(btree p) {
|
|
|
if (!(p->lch) && !(p->rch)) {
|
|
|
cout << fixed << setprecision(1) << p->data << " ";
|
|
|
} else cout << p->op << " ";
|
|
|
}
|
|
|
|
|
|
int i;
|
|
|
|
|
|
double get_num(string s) {
|
|
|
double x = 0;
|
|
|
while (is_digit(s[i])) {
|
|
|
x = x * 10 + s[i] - '0';
|
|
|
i++;
|
|
|
}
|
|
|
if (s[i] == '.') {
|
|
|
double k = 10.0, y = 0;
|
|
|
i++;
|
|
|
while (is_digit(s[i])) {
|
|
|
y += ((s[i] - '0') / k);
|
|
|
i++;
|
|
|
k *= 10;
|
|
|
}
|
|
|
x += y;
|
|
|
}
|
|
|
return x;
|
|
|
}
|
|
|
|
|
|
void create(btree &T, string s) {
|
|
|
T = new node;
|
|
|
while (i < s.length() && (s[i] == ' ' || s[i] == '.')) i++;
|
|
|
if (i >= s.length()) {
|
|
|
T->lch = T->rch = NULL;
|
|
|
return;
|
|
|
}
|
|
|
if (is_digit(s[i])) {
|
|
|
T->data = get_num(s);
|
|
|
T->lch = T->rch = NULL;
|
|
|
i++;
|
|
|
return;
|
|
|
} else {
|
|
|
T->op = s[i];
|
|
|
i += 2;
|
|
|
create(T->lch, s);
|
|
|
create(T->rch, s);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void pre_order(btree T) { //前序遍历
|
|
|
if (T != NULL) {
|
|
|
print(T);
|
|
|
pre_order(T->lch);
|
|
|
pre_order(T->rch);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void in_order(btree T) { //中序遍历
|
|
|
if (T != NULL) {
|
|
|
in_order(T->lch);
|
|
|
print(T);
|
|
|
in_order(T->rch);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void post_order(btree T) { //后序遍历
|
|
|
if (T != NULL) {
|
|
|
post_order(T->lch);
|
|
|
post_order(T->rch);
|
|
|
print(T);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
double cal_tree(btree &T) {
|
|
|
if (T != NULL) {
|
|
|
if (!(T->lch) && !(T->rch)) {
|
|
|
return T->data;
|
|
|
} else return E.cal(cal_tree(T->lch), cal_tree(T->rch), T->op);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int main() {
|
|
|
int T;
|
|
|
cin >> T;
|
|
|
string str;
|
|
|
getline(cin, str);
|
|
|
while (T--) {
|
|
|
getline(cin, str);
|
|
|
string pre = E.get_prefix(str), post = E.get_postfix(str);
|
|
|
cout << "前缀表达式:" << pre << endl;
|
|
|
cout << "后缀表达式:" << post << endl;
|
|
|
|
|
|
btree tree;
|
|
|
i = 0; //全局变量记录string下标,递归建立表达式树
|
|
|
create(tree, pre);
|
|
|
cout << "前序遍历:";
|
|
|
pre_order(tree);
|
|
|
cout << endl;
|
|
|
cout << "中序遍历:";
|
|
|
in_order(tree);
|
|
|
cout << endl;
|
|
|
cout << "后序遍历:";
|
|
|
post_order(tree);
|
|
|
cout << endl;
|
|
|
cout << "后缀表达式计算结果:" << fixed << setprecision(6) << E.solve(str) << endl;
|
|
|
cout << "表达式树结果:" << fixed << setprecision(6) << cal_tree(tree) << endl << endl;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
/*
|
|
|
测试样例:
|
|
|
1000
|
|
|
1 + 2
|
|
|
1 + 2 - 3 / 4 * 5
|
|
|
1 + 2 * (3 - 4) - 5 / 6
|
|
|
1+2*3-4/(5-6*7+8)/9
|
|
|
1-2+3*4%(5+6-7/8)+9
|
|
|
1+(2-3)*4*(5-6+7/8)/9
|
|
|
11+(22-33)*44*(55-6+7/8)/9
|
|
|
19+(28-37)*46*(55-64+73/82)/91
|
|
|
1.2+(2.421-3.3123)*4.0*(5.42342-6+7.2*8.13)/9.1321
|
|
|
*/ |