逆波兰表达式求值通过栈实现:遍历token,数字压栈,运算符弹出栈顶两元素(先弹为右操作数),执行对应运算后压栈,最终栈中唯一元素即结果。

一、逆波兰表达式求值的栈模拟实现
逆波兰表达式(后缀表达式)无需括号且运算符位于操作数之后,其求值天然适配栈结构:每读到数字则压栈,每读到运算符则弹出栈顶两元素进行计算,并将结果压回栈中。该方法避免递归与优先级判断,时间复杂度稳定为O(n)。
1、初始化一个空栈用于存储操作数。
2、遍历输入字符串数组中的每个token。
3、若token为数字(含负数,如"-123"),将其转换为int并压入栈。
立即学习“C++免费学习笔记(深入)”;
4、若token为"+",弹出栈顶两个元素y(先弹)、x(后弹),执行x + y,结果压栈。
5、若token为"-",弹出y、x,执行x - y,结果压栈。
6、若token为"*",弹出y、x,执行x * y,结果压栈。
7、若token为"/",弹出y、x,执行向零截断的整数除法 x / y(C++中-3/2为-1,非向下取整),结果压栈。
8、遍历结束后,栈中唯一元素即为表达式结果。
二、基于递归下降的算术语法树构建与深度计算
将逆波兰表达式反向重构为语法树需先还原为中缀结构或直接按操作数/运算符比例建树;此处采用自底向上构造方式:每个运算符节点必有两个子节点(左、右操作数),叶节点均为数字。树深度定义为根到最远叶节点的边数,反映嵌套计算层级。
1、使用栈存储TreeNode*指针,初始为空。
2、对每个token:若为数字,创建叶节点(val=数字,left=nullptr,right=nullptr),压栈。
3、若为运算符,弹出栈顶两个节点作为右子、左子(注意顺序),创建新节点(val=运算符,left=左子,right=右子),压栈。
4、最终栈中唯一节点即为根节点。
5、编写递归函数depth(TreeNode* node),返回以node为根的子树深度:若node为空返回0;否则返回1 + max(depth(node->left), depth(node->right))。
三、迭代式语法树深度求解(避免递归栈溢出)
对大型逆波兰表达式生成的深层树,递归可能导致栈溢出;可改用显式栈模拟DFS,记录每个节点及其当前已探索子树的最大深度,从而在常数空间内完成深度统计。
1、定义结构体StackNode { TreeNode* node; int depth_so_far; }。
2、初始化栈,压入{root, 1}(根节点深度为1)。
3、初始化max_depth = 0。
4、当栈非空时:弹出顶部StackNode,更新max_depth = max(max_depth, current.depth_so_far)。
5、若current.node->right非空,压入{current.node->right, current.depth_so_far + 1}。
6、若current.node->left非空,压入{current.node->left, current.depth_so_far + 1}。
7、循环结束后,max_depth即为整棵树的深度。
四、运算符优先级隐含深度映射验证法
逆波兰表达式虽无显式括号,但其token序列顺序隐含了原中缀表达式的结合结构;通过统计连续操作数与运算符交替频次,可反推最小可能语法树深度,用于交叉验证前述构造结果的合理性。
1、扫描token序列,维护count_num(当前连续操作数个数)和max_depth_est(估计深度)。
2、遇到数字:count_num++。
3、遇到运算符:若count_num >= 2,则count_num减1(因两数归约为一结果),并更新max_depth_est = max(max_depth_est, count_num)。
4、若count_num == 1且后续为运算符,说明存在单目运算或格式错误,应报错。
5、全程保持count_num始终 ≥ 1,否则表达式无效(如"1 2 + +"会导致count_num=0)。
五、内存安全的字符串token分割与数字解析优化
原始输入为单一字符串(如"2 1 + 3 *"),需可靠切分token并识别负数("-5"非减号);标准strtok破坏原串且不支持空格外分隔符,此处采用手动扫描避免额外内存拷贝与异常中断。
1、使用size_t i = 0遍历字符串,跳过前导空格。
2、若s[i]为'-'且i+1
3、若s[i]为数字,向后收集连续数字字符。
4、每次提取完整token后,调用std::stoi(s.substr(start, len)),捕获std::out_of_range异常。
5、对每个成功解析的整数,检查是否满足INT_MIN ≤ value ≤ INT_MAX,越界则抛出invalid_argument。


















