中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)

前言: 中缀表达式转后缀表达式也是近年来找工作笔试、面试、考研机试,算法竞赛中的考点,所以学会它也是很有必要的,因为这种问题的代码比较模板化,建议读者直接背诵模板,但是不能死记硬背,而是在理解算法思路的基础上背诵此代码。

读者可以先阅读这篇博客 —> 博客传送门

因为表达式求值中的代码中隐含了一步,即将中缀表达式转换成后缀表达式,因此只需要将表达式求值的代码稍作修改即可得到中缀表达式转后缀表达式的代码。

题目

给定一个中缀表达式,其中运算符仅包含 + , − , ∗ , / +,-,*,/ +,,,/(加 减 乘 整除),可能包含括号,请你将中缀表达式转换成后缀表达式。

输入

( 2 ∗ 1 + 6 ) ∗ ( 5 − 3 ) / 4 (2*1+6)*(5-3)/4 (21+6)(53)/4

输出

2 2 2 1 1 1 ∗ * 6 6 6 + + + 5 5 5 3 3 3 − - ∗ * 4 4 4 / / /

实现思路

  1. 若碰到操作数,直接输出在后缀表达式中;
  2. 若碰到左括号,直接将左括号压入操作符栈中;
  3. 若碰到右括号,弹出操作符栈中的操作符直到碰到左括号为止,弹出操作符将操作符输出在后缀表达式中;
  4. 若碰到操作符,弹出操作符栈中优先级 大于或者等于 大于或者等于 大于或者等于该操作符的元素(若碰到到左括号或者栈为空应该停止),弹出操作符将操作符输出在后缀表达式中;
  5. 若扫描完字符串后,运算符栈不为空,弹出操作符输出在后缀表达式中直到栈为空,算法结束;

手动模拟

步骤1
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第1张图片
步骤2
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第2张图片
步骤3
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第3张图片
步骤4
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第4张图片
步骤5
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第5张图片
步骤6
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第6张图片
步骤7
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第7张图片
步骤8
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第8张图片
步骤9
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第9张图片
步骤10
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第10张图片
步骤11
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第11张图片
步骤12
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第12张图片
步骤13
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第13张图片
步骤14
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第14张图片
步骤15
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第15张图片
步骤16
中缀表达式转后缀表达式C++代码(有完整实现思路,代码附有详细注释)_第16张图片

代码(附详细注释)

#include
#include
#include
#include
using namespace std;

//定义操作符栈和操作数栈
stack<char> op;

//弹出操作符,输出操作符
void eval(){
    char c = op.top();
    op.pop();
    cout << c << " ";
}

int main(){
    //读入表达式字符串
    string s;
    cin >> s;
    
    //定义四个操作符的优先级; 加减的优先级比乘除低,这里定义加减是1,乘除是2
    map<char, int> mp = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};
    
    //从左到右扫描一遍字符串
    for(int i = 0; i < s.size(); i++){
        //四种情况分别对应该字符是数字,左括号,右括号,操作符
        if(isdigit(s[i])){
            //operand存储操作数,因为操作数在字符串里面可能有连续几位
            int j = i, operand = 0;
            //这段代码不要害怕,实际上是将字符串"1234"转换成数字1234的代码
            while(j < s.size() && isdigit(s[j])){
                operand = operand * 10 + s[j] - '0';
                j++;
            }
            cout << operand << " "; //遇到操作数直接输出在表达式
            i = j - 1; //for循环里面会执行i++,所以这里j需要减去1
        }else if(s[i] == '('){
            op.push(s[i]); //左括号则压栈
        }else if(s[i] == ')'){
            //右括号则一直匹配,直到碰到左括号位置
            while(op.top() != '(') eval();
            op.pop();
        }else{
            //若栈不为空且没有碰到左括号且栈顶元素的优先级大于等于该操作符的优先级
            while(op.size() && op.top() != '(' && mp[op.top()] >= mp[s[i]])
                eval();
            op.push(s[i]); //将操作符压入栈中
        }
    }
    //操作到运算符栈空为止
    while(op.size()) eval();
    return 0;
}

注意

  1. 实现中缀表达式转后缀表达式,只需要将表达式求值的代码中有关操作数栈的代码删除,改成遇见操作数直接输出操作数,操作运算符直接输出即可;
  2. 只要理解了表达式求值的代码,中缀表达式转后缀表达式代码稍作修改,直接背诵
  3. 其他的注意点请见这篇博客 —>博客传送门

如果觉得对你有所帮助的话,麻烦你点赞,收藏,关注我,后期还会更新博客

你可能感兴趣的:(模板题,算法,c++,算法,数据结构)