You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
8.6 KiB

2 years ago
#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
*/