【数据结构与算法】栈的应用

👨‍💻 关于作者:会编程的土豆

"不是因为看见希望才坚持,而是坚持了才看见希望。"

你好,我是会编程的土豆,一名热爱后端技术的Java学习者。

📚 正在更新中的专栏:

💕作者简介:后端学习者

一文搞懂中缀表达式与后缀表达式(栈的经典应用,附完整代码)

在数据结构与算法中,"中缀 → 后缀 → 计算"的问题是栈的经典应用之一,不仅是考试高频,也是面试常考点。很多人一开始会觉得规则很多、过程很乱,其实本质非常清晰:用栈来处理运算符优先级

这篇文章带你从零搞懂三件事:什么是中缀/后缀表达式;如何把中缀转后缀;如何计算后缀表达式。


一、三种表达式形式

1. 中缀表达式(我们平时写的)

复制代码
3 + 4 * 2

特点:

  • 运算符在中间

  • 需要考虑优先级和括号


2. 后缀表达式(逆波兰表达式)

复制代码
3 4 2 * +

特点:

  • 运算符在后面

  • 不需要括号

  • 可以直接用栈计算


3. 前缀表达式(了解即可)

复制代码
+ 3 * 4 2

这篇重点讲中缀和后缀。


二、为什么要转后缀?

中缀表达式难点在于:

  • 有优先级(* 比 + 高)

  • 有括号

而后缀表达式:

完全不需要优先级规则,直接算

所以思路是:

复制代码
中缀表达式 → 转后缀 → 用栈计算

三、中缀转后缀(核心)

规则总结(一定要理解)

遍历中缀表达式:

  1. 遇到数字 → 直接输出

  2. 遇到运算符 →

    • 栈空 → 入栈

    • 栈顶优先级 ≥ 当前 → 弹出再入栈

  3. 遇到 '(' → 入栈

  4. 遇到 ')' → 一直弹到 '('


运算符优先级函数

复制代码
int priority(char op) {
    if (op == '+' || op == '-') return 1;
    if (op == '*' || op == '/') return 2;
    return 0;
}

中缀转后缀完整代码

cpp 复制代码
#include <iostream>
#include <stack>
using namespace std;

string infixToPostfix(string s) {
    stack<char> st;
    string result = "";

    for (char c : s) {
        if (isdigit(c)) {
            result += c;  // 数字直接输出
        }
        else if (c == '(') {
            st.push(c);
        }
        else if (c == ')') {
            while (!st.empty() && st.top() != '(') {
                result += st.top();
                st.pop();
            }
            st.pop(); // 弹出 '('
        }
        else { // 运算符
            while (!st.empty() && priority(st.top()) >= priority(c)) {
                result += st.top();
                st.pop();
            }
            st.push(c);
        }
    }

    while (!st.empty()) {
        result += st.top();
        st.pop();
    }

    return result;
}

举个例子

复制代码
中缀:3+4*2

过程:

复制代码
3 → 输出
+ → 入栈
4 → 输出
* → 入栈(优先级更高)
2 → 输出

最终:

复制代码
后缀:342*+

四、后缀表达式计算

后缀表达式的计算更简单:

核心规则

  1. 遇到数字 → 入栈

  2. 遇到运算符 → 弹出两个数计算,再入栈


完整代码

cpp 复制代码
#include <stack>
#include <iostream>
using namespace std;

int evaluatePostfix(string s) {
    stack<int> st;

    for (char c : s) {
        if (isdigit(c)) {
            st.push(c - '0');
        }
        else {
            int b = st.top(); st.pop();
            int a = st.top(); st.pop();

            if (c == '+') st.push(a + b);
            if (c == '-') st.push(a - b);
            if (c == '*') st.push(a * b);
            if (c == '/') st.push(a / b);
        }
    }

    return st.top();
}

举个例子

复制代码
后缀:342*+

计算过程:

复制代码
3 → 入栈
4 → 入栈
2 → 入栈
* → 4*2=8 入栈
+ → 3+8=11

结果:

复制代码
11

五、整体流程总结

复制代码
中缀表达式
   ↓(栈)
后缀表达式
   ↓(栈)
最终结果

六、常见坑点

1. 弹栈顺序不能错

复制代码
int b = st.top(); st.pop();
int a = st.top(); st.pop();

不是 a 和 b 随便写!


2. 忘记处理括号

复制代码
遇到 ')' 一定要弹到 '('

3. 优先级判断写错

复制代码
priority(st.top()) >= priority(c)

七、进阶方向

学完这一块,可以继续提升:

  • 支持多位数(如 123)

  • 支持负数

  • 支持空格解析

  • 直接计算中缀(不转后缀)


八、一句话总结

中缀难在"优先级",后缀强在"可直接计算",而栈就是连接两者的桥梁。

相关推荐
神仙别闹1 小时前
基于C++实现的简单的SMTP服务器
服务器·开发语言·c++
菜菜的顾清寒1 小时前
力扣hot100(17) 缺失的第一个正数
算法·leetcode·职场和发展
光泽雨1 小时前
c#数值类型之间的自动转换
java·算法·c#
ZPC82101 小时前
moveit2 servo -movegroup aciton client arm_controller -rviz2
人工智能·算法·计算机视觉·机器人
程序设计基础课组2 小时前
codeblock找不到MINGW64编译器怎么办?
c++·codeblocks
xcjbqd02 小时前
Qt Quick中QML与C++交互详解及场景切换实现
c++·qt·交互
Mem0rin2 小时前
[Java/数据结构]PriorityQueue
java·数据结构
!停2 小时前
C++入门STL容器string使用基础
开发语言·c++
m0_716765232 小时前
数据结构--栈的插入、删除、查找详解
开发语言·数据结构·c++·经验分享·学习·青少年编程·visual studio