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

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

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

你好,我是会编程的土豆,一名热爱后端技术的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)

  • 支持负数

  • 支持空格解析

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


八、一句话总结

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

相关推荐
执子星海4 分钟前
Registry Win32 API详解
c++·windows·microsoft·visualstudio·微软
AI服务老曹10 分钟前
车牌识别算法接入AI视频分析平台的流程和误报优化
人工智能·算法·音视频
江屿风24 分钟前
C++OJ题经验总结(竞赛)5
开发语言·c++
神威难绷泪27 分钟前
Linux应用软件编程:线程分离属性 互斥机制 同步机制 死锁
linux·开发语言·算法·线程
小星星闪亮登场44 分钟前
图论--最小生成树(内含二分图)
数据结构·算法·图论·迭代加深·图搜索算法
ZC跨境爬虫1 小时前
LeetCode 219. 存在重复元素 II(滑动窗口 + 哈希表详解)
算法·leetcode·散列表
zh路西法1 小时前
【玩转VLA具身智能机械臂】(三):视觉避障——从 RGB-D 点云到 MoveIt octomap 的完整落地
c++·ros2·gazebo·moveit2·ompl·octomap
吞下星星的少年·-·1 小时前
The 2025 ICPC Asia East Continent Online Contest (I) A题(模拟+贪心)
算法·贪心·模拟
小程序设计2 小时前
【机械设计】磁粉检测机器人的设计与验证
算法·机器人
Navigator_Z2 小时前
LeetCode //C - 1220. Count Vowels Permutation
c语言·算法·leetcode