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. 总结

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

相关推荐
wuyk5551 小时前
21. 嵌入式面试避坑指南:sizeof 是关键字,不是函数!
c语言·开发语言·stm32·单片机·嵌入式硬件
2601_962440841 小时前
计算机毕业设计之jsp教室管理系统
java·开发语言·笔记·分布式·算法·课程设计·推荐算法
apocelipes2 天前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
RainCity5 天前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
LinXunFeng13 天前
Obsidian - 使用 Share Note 分享笔记并自部署
前端·笔记·github
LDR00617 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
通信小呆呆17 天前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
H__Rick17 天前
自动对焦学习-3
人工智能·学习·计算机视觉
Daisy Lee17 天前
量化学习-第1章-什么是量化金融
学习·金融·datawhale