计算中缀表达式的总结
后缀表达式是怎么产生的?
中缀式转后缀式的方法
加括号后移——适合在做客观题时候
举个例子,一个式子:
( 5 + 20 + 1 ∗ 3 ) / 14 (5+20+1∗3)/14 (5+20+1∗3)/14
如何把该式子转换成后缀表达式呢?其实就是分三步:
- 按运算符优先级对所有运算符和它的运算数加括号,(原本的括号不用加)
- 把运算符移到对应的括号后
- 去掉括号
具体实现为:
- ( ( ( 5 + 20 ) + ( 1 ∗ 3 ) ) / 14 ) (((5+20)+(1∗3))/14) (((5+20)+(1∗3))/14)
- ( ( ( 520 ) + ( 13 ) ∗ ) + 14 ) / ( ( ( 520 ) + ( 13 ) ∗ ) + 14 ) / (((520)+(13)∗)+14)/(((520)+(13)∗)+14)/ (((520)+(13)∗)+14)/(((520)+(13)∗)+14)/
- 520 + 13 ∗ + 14 / 520+13∗+14/ 520+13∗+14/
适合编程的实现(使用栈)
参考这个例子: https://blog.csdn.net/update7/article/details/70404798?tdsourcetag=s_pctim_aiomsg
- 满足以下步骤
- 如果遇到操作数,我们就直接将其输出。
- 如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
- 如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
- 如果遇到任何其他的操作符,如 ( “ + ” , “ ∗ ” , “ ( ” ) (“+”, “*”,“(”) (“+”,“∗”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到 " ) " 的情况下我们才弹出" ( “,其他情况我们都不会弹出” ( "。
- 如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 2e6 + 7;
stack <char> S;
int getPriority(char ch) {
if (ch == '+' || ch == '-') return 1;
else if (ch == '*' || ch == '/') return 2;
else return 0;
}
int main() {
int n;
cin >> n;
while (n--) {
char x[maxn];
cin >> x;
for (long long i = 0; i < strlen(x); ++i) {
if (x[i] >= '0' && x[i] <= '9') {//遇到数字直接输出
cout << x[i];
}
if (x[i] == ')') {//遇到')'输出所有栈内的运算符
while (S.top() != '(') {
cout << S.top();
S.pop();
}
S.pop();
}
if (x[i] == '(' || x[i] == '+' || x[i] == '-' || x[i] == '*' || x[i] == '/') {//遇到'('直接入栈,其余的比较优先级,输出栈顶所有优先级比当前大等的,再将当前的运算符入栈
while (!S.empty() && x[i] != '(' && getPriority(x[i]) <= getPriority(S.top())) {
cout << S.top();
S.pop();
}
S.push(x[i]);
}
}
while (!S.empty()) {
cout << S.top();
S.pop();
}
return 0;
}
适合编程的实现(使用二叉树)
一些例题
后缀式求值
描述
我们人类习惯于书写“中缀式”,如 3 + 5 * 2
,其值为13
。 (p.s. 为什么人类习惯中缀式呢?是因为中缀式比后缀式好用么?)
而计算机更加习惯“后缀式”(也叫“逆波兰式”,Reverse Polish Notation)。上述中缀式对应的后缀式是: 3 5 2 * +
现在,请对输入的后缀式进行求值。
输入
在一行中输入一个后缀式,运算数和运算符之间用空格分隔,运算数长度不超过6位,运算符仅有+ - * /
四种。
输出
在一行中输出后缀式的值,保留一位小数。
输入样例
3 5.4 2.2 * +
输出样例
14.9
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
stack<double> sta;
string x;
while (cin >> x) {
if (x == "+" || x == "-" || x == "*" || x == "/") {
double a = sta.top();
sta.pop();
double b = sta.top();
sta.pop();
if (x == "+") sta.push(b + a);
else if (x == "-") sta.push(b - a);
else if (x == "*") sta.push(b * a);
else if (x == "/") sta.push(b / a);
} else sta.push(stod(x));
}
printf("%.1lf", sta.top());
return 0;
}
PS:一些奇技淫巧
- C++字符串数值的转换
string s1 = "2018.11";
int a1 = stoi(s1);
double c = stod(s1);
float d = stof(s1);
int a2 = a1 + 1;
中缀表达式转换为后缀表达式并求值
描述
把题目给出中缀表达式转换为后缀表达式输出,并求后缀表达式的值。为简单起见,我们约定:1、输入的中缀表达式一定是合法的,并且只含数字,四种运算符+、-、*、/和小括号;2、运算数都是一位正整数(1~9);3、输入的中缀表达式不超过20个字符;4、除法运算的结果仍然是正整数。
输入
输入的第一行是一个正整数 N ,表示以下有 N 行。每行是一个中缀表达式。为简单起见,我们约定:1、输入的中缀表达式一定是合法的,并且只含数字,四种运算符+、-、*、/和小括号;2、运算数都是一位正整数(1~9);3、输入的中缀表达式不超过20个字符;4、除法运算的结果仍然是正整数。
输出
输出每行中缀表达式所对应后缀表达式,隔一个空格之后,输出该后缀表达式计算之后得到的值
输入样例
6
2+4
3+2*7
2*(4+6)
(5/2+4)*5+2
(3+5)*(7-2)/4
5*(8-(3+2))
输出样例
24+ 6
327*+ 17
246+* 20
52/4+5*2+ 32
35+72-*4/ 10
5832+-* 15
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 2e6 + 7;
stack<char> S;
queue<char> Q;
int getPriority(char ch) {
if (ch == '(') return 1;
else if (ch == '+' || ch == '-') return 2;
else if (ch == '*' || ch == '/') return 3;
}
int main() {
int n;
cin >> n;
while (n--) {
char x[maxn];
cin >> x;
for (long long i = 0; i < strlen(x); ++i) {
if (x[i] >= '0' && x[i] <= '9') {
cout << x[i];
Q.push(x[i]);
}
if (x[i] == ')') {
while (S.top() != '(') {
Q.push(S.top());
cout << S.top();
S.pop();
}
S.pop();
}
if (x[i] == '(' || x[i] == '+' || x[i] == '-' || x[i] == '*' || x[i] == '/') {
while (!S.empty() && getPriority(x[i]) <= getPriority(S.top()) && x[i] != '(') {
Q.push(S.top());
cout << S.top();
S.pop();
}
S.push(x[i]);
}
}
while (!S.empty()) {
Q.push(S.top());
cout << S.top();
S.pop();
}
cout << " ";
stack<int> st;
while (!Q.empty()) {
char ch = Q.front();
if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
double a = st.top();
st.pop();
double b = st.top();
st.pop();
if (ch == '+') st.push(b + a);
else if (ch == '-') st.push(b - a);
else if (ch == '*') st.push(b * a);
else if (ch == '/') st.push(b / a);
} else st.push(ch - '0');
Q.pop();
}
cout << st.top() << endl;
}
return 0;
}