计算中缀表达式

计算中缀表达式的总结

后缀表达式是怎么产生的?

中缀式转后缀式的方法

加括号后移——适合在做客观题时候

举个例子,一个式子:

( 5 + 20 + 1 ∗ 3 ) / 14 (5+20+1∗3)/14 (5+20+13)/14

如何把该式子转换成后缀表达式呢?其实就是分三步:

  1. 按运算符优先级对所有运算符和它的运算数加括号,(原本的括号不用加)
  2. 把运算符移到对应的括号后
  3. 去掉括号

具体实现为:

  1. ( ( ( 5 + 20 ) + ( 1 ∗ 3 ) ) / 14 ) (((5+20)+(1∗3))/14) (((5+20)+(13))/14)
  2. ( ( ( 520 ) + ( 13 ) ∗ ) + 14 ) / ( ( ( 520 ) + ( 13 ) ∗ ) + 14 ) / (((520)+(13)∗)+14)/(((520)+(13)∗)+14)/ (((520)+(13))+14)/(((520)+(13))+14)/
  3. 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值