逆波兰表达式通过栈结构求值:遍历token,数字入栈,运算符弹出两数计算后入栈,除法向零截断,最终栈顶即结果;token分割用stringstream安全提取;运算符查表优化提升可扩展性。

一、使用栈结构逐字符解析并计算逆波兰表达式
逆波兰表达式(后缀表达式)的求值依赖于栈的后进先出特性,遇到操作数则压入栈,遇到运算符则弹出栈顶两个元素进行相应运算,并将结果重新压入栈。该方法严格遵循表达式从左到右扫描顺序,无需考虑运算符优先级与括号嵌套。
1、初始化一个空栈用于存储操作数。
2、遍历输入字符串数组中的每个 token。
3、若当前 token 为数字(含负数,如 "-12"),将其转换为整型并压入栈。
立即学习“C++免费学习笔记(深入)”;
4、若当前 token 为 "+"、"-"、"*" 或 "/",则从栈中依次弹出两个整数:先弹出的是右操作数,后弹出的是左操作数。
5、执行对应算术运算:对除法需向零截断,例如 13 / 5 得 2,-13 / 5 得 -2。
6、将运算结果压入栈。
7、遍历结束后,栈中唯一剩余元素即为表达式最终结果。
二、预处理字符串并分割 token 的安全切分法
原始输入为单个字符串(如 "2 1 + 3 *"),需按空白符可靠分割为独立 token,同时兼容连续空格、首尾空格及负数符号不被误判为减法运算符。此步骤确保后续栈处理接收的是语义明确的操作单元。
1、使用 std::stringstream 构造输入流,自动跳过任意空白符。
2、循环调用 >> 运算符提取子字符串,每次提取一个 token。
3、将每个 token 存入 std::vector<:string> 容器,保持原始顺序。
4、检查 token 是否为空字符串,若为空则跳过,避免非法访问。
5、对每个非空 token 判断首字符:若为 '-' 且长度大于 1 且后续字符全为数字,则视为负数;否则视为减法运算符。
三、使用 std::stack 实现类型安全的整数栈操作
标准库 stack 容器适配器提供 O(1) 时间复杂度的 push、top 和 pop 操作,且模板参数限定为 int 类型,可防止浮点数或字符串混入导致的隐式转换错误,保障算术运算的类型一致性与溢出可控性。
1、声明栈对象:std::stack
2、压入操作使用 stk.push(value),value 必须为 int 类型。
3、取栈顶值前必须判断栈大小是否 ≥ 2:若 stk.size() 。
4、获取左操作数:int b = stk.top(); stk.pop(); int a = stk.top(); stk.pop();
5、执行运算后,stk.push(result) 将结果压回栈中。
四、手动实现简易栈结构以规避 STL 依赖
在嵌入式环境或禁止使用 STL 的约束下,可用固定大小数组模拟栈行为,通过索引 top_idx 管理栈顶位置,所有操作均基于数组下标完成,无动态内存分配,确定性高且内存布局连续。
1、定义 int stack[10000]; 和 int top_idx = -1; 表示空栈。
2、压栈操作:top_idx++; stack[top_idx] = value; 需在 top_idx++ 前检查 top_idx 。
3、弹栈操作:if (top_idx >= 0) { value = stack[top_idx]; top_idx--; }。
4、取栈顶值:if (top_idx >= 0) val = stack[top_idx];。
5、计算完成后,返回 stack[0](当 top_idx == 0 时)作为最终结果。
五、运算符识别与分支调度的查表优化法
避免冗长 if-else 链,采用静态 const std::unordered_map<:string std::function>> 映射运算符字符串到对应 lambda 函数,提升可读性与扩展性,新增运算符只需插入新键值对而无需修改主逻辑。
1、在函数外层静态定义映射表,包含 "+", "-", "*", "/" 四个键。
2、每个值为形如 [](int a, int b) { return a + b; } 的 lambda 表达式。
3、遍历时对 token 查表:auto it = ops.find(token); if (it != ops.end()) { ... }。
4、执行 it->second(left, right) 获取结果,注意传参顺序:left 为先弹出的第二元素,right 为后弹出的第一元素。
5、若查表失败且 token 不是数字,则抛出异常或返回错误码表示非法 token。


















