C语言学习笔记20260703-牛牛与后缀表达式(逆波兰表达式)

C语言学习笔记20260703-牛牛与后缀表达式(逆波兰表达式)

1. 题目概述

本题要求计算一个特定格式的后缀表达式的值。

  • 输入格式 :字符串 s,数字以 # 结尾作为分隔符,运算符为 +-*
  • 示例12#3#+15#* 中缀形式 (12+3)*15 结果 225
  • 数据范围 :字符串长度可达 10610^6106,运算结果绝对值不超过 101810^{18}1018(需使用 long long)。

2. 核心知识点:栈的应用

后缀表达式(又称逆波兰表达式)是计算机科学中经典的**栈(Stack)**应用场景。其求值过程不需要考虑运算符优先级或括号,算法逻辑非常直接。

算法流程

从左到右扫描表达式字符串:

  1. 遇到数字:解析出完整的数值,将其压入栈中。
  2. 遇到运算符
    • 从栈顶弹出两个元素。
    • 注意顺序 :先弹出的是右操作数 ,后弹出的是左操作数
    • 执行运算,将结果压回栈中。
  3. 结束:扫描完成后,栈中剩下的唯一元素即为最终结果。

⚠️ 易错点 :减法和除法不满足交换律。若栈中元素为 [a, b](b在栈顶),遇到 - 时,应计算 a - b,而非 b - a


3. 代码实现与解析

以下是基于 C 语言的数组模拟栈解法:

c 复制代码
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 给定一个后缀表达式,返回它的结果
 * @param str string字符串 
 * @return long长整型
 */
long long legalExp(char* str) 
{
    // 定义足够大的数组模拟栈,防止溢出
    const int MAXN = 1000005;
    long long stack[MAXN];
    
    // top 指向栈顶元素的下一个位置(即当前栈内元素个数)
    int top = 0;
    int len = strlen(str);
    long long num = 0; // 用于暂存正在拼接的数字

    for(int i = 0; i < len; i++)
    {
        char c = str[i];
        
        // 1. 处理数字字符
        if(c >= '0' && c <= '9')
        {
            // 累加构建多位数 (例如 "12" -> 1*10 + 2)
            num = num * 10 + (c - '0');
        }
        // 2. 处理数字结束标志 '#'
        else if(c == '#')
        {
            // 将构建好的数字入栈
            stack[top++] = num;
            num = 0; // 重置数字缓存
        }
        // 3. 处理运算符
        else if(c == '+' || c == '-' || c == '*')
        {
            // 取出右操作数(栈顶)
            long long b = stack[--top];
            // 取出左操作数(新栈顶)
            long long a = stack[--top];
            
            long long res;
            switch(c)
            {
                case '+': res = a + b; break;
                case '-': res = a - b; break; // 注意是 a - b
                case '*': res = a * b; break;
                default:  res = 0;
            }
            
            // 将运算结果压回栈中
            stack[top++] = res;
        }
    }
    
    // 最终栈顶元素即为结果,top指向栈顶元素的下一个位置(即当前栈内元素个数)
    return stack[top - 1];
}

关键细节分析

  1. 多位数的处理

    题目中数字可能不止一位(如 12)。代码中使用变量 num 进行累加 (num = num * 10 + ...),直到遇到 # 才确认数字结束并入栈。这是处理流式数字输入的常用技巧。

  2. 栈的实现方式

    这里使用了静态数组 stack[MAXN] 配合整数下标 top 来模拟栈。相比于 STL 的 std::stack,数组模拟在竞赛或高性能场景下通常更快,且能精确控制内存大小。

  3. 数据类型

    题目提示结果可能很大,因此栈和操作数必须使用 long long 类型,防止整数溢出。


4. 复杂度分析

  • 时间复杂度 :O(N)O(N)O(N)。其中 NNN 为字符串长度。我们只需要遍历一次字符串,每个字符的处理(入栈、出栈、计算)都是 O(1)O(1)O(1) 的操作。
  • 空间复杂度 :O(N)O(N)O(N)。最坏情况下(例如所有数字都在前面,运算符在最后),栈的大小可能接近 N/2N/2N/2。

5. 总结

本题是后缀表达式求值的模板题。掌握此题的关键在于理解**"遇数入栈,遇符计算"**的原则,并正确处理多位数的解析以及运算数的左右顺序。这种基于栈的计算模型也是许多编译器和计算器底层实现的基础。

相关推荐
克里斯蒂亚诺更新14 小时前
ruoyi角色权限的对应关系
笔记
a11177617 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao17 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
人邮异步社区17 小时前
怎么把C语言学到精通?
c语言·开发语言
破碎的南瓜18 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
你想知道什么?19 小时前
线性回归-学习笔记
笔记·学习·线性回归
鱼毓屿御19 小时前
从「只会聊」到「边想边做」的跃迁
前端·学习·react.js
谙弆悕博士19 小时前
系统集成项目管理工程师教程(第3版)笔记——第17章:法律法规和标准规范
笔记·职场和发展·学习方法·业界资讯·软考·法律·法规
AOwhisky20 小时前
Python 学习笔记(第十五期)——运维自动化(下·后篇):堡垒机实战——paramiko高阶篇
运维·python·学习·云原生·自动化·运维开发
谙弆悕博士21 小时前
系统集成项目管理工程师教程(第3版)笔记——第4章:信息系统架构
笔记·系统架构·项目管理·创业创新·学习方法·业界资讯·物理