【数据结构+算法】进栈顺序推算、卡特兰数与逆波兰表达式

在数据结构与算法领域,栈的操作与应用、卡特兰计数问题、表达式解析值得关注。以下详细解释:

1.基础结构:进栈顺序

1)进栈顺序的基本概念

进栈顺序(Push Order)是指元素按照特定顺序被压入栈中的过程。栈遵循后进先出(LIFO)原则,即:最后压入的元素最先被弹出。理解进栈顺序的推算是分析栈操作和解决相关问题的基础。

2)栈的操作规则

栈支持两种基本操作:

  • Push(压栈):将元素添加到栈的顶部。
  • Pop(弹栈):移除并返回栈顶的元素。

任何合法的栈操作序列必须满足:在弹出某个元素之前,该元素必须已被压入栈中,且未被提前弹出。

3)推算进栈顺序的步骤

给定一个栈的输入序列和输出序列,可以通过模拟栈的操作来验证其合法性:

  1. 初始化一个空栈和一个指向输入序列开头的指针;
  2. 遍历输出序列中的每个元素,检查是否可以通过压栈或弹栈操作得到该元素;
  3. 若当前栈顶元素与输出序列的当前元素匹配,则弹栈并移动到输出序列的下一个元素;
  4. 若不匹配,则从输入序列中压入下一个元素到栈中,直到匹配或输入序列耗尽;
  5. 若输入序列耗尽且栈顶元素仍不匹配,则输出序列不合法。

4)示例分析

假设输入序列为 [1, 2, 3, 4, 5],输出序列为 [4, 5, 3, 2, 1]

  • 压入 1, 2, 3, 4,弹出 4
  • 压入 5,弹出 5
  • 弹出 3, 2, 1
    此输出序列合法。

若输出序列为 [4, 3, 5, 1, 2]

  • 弹出 4, 3 后,栈中剩余 [1, 2]
  • 弹出 5 时需压入 5,但 12 被压在栈底,无法提前弹出。
    此序列不合法。

5)合法序列的数学性质

对于长度为 nnn 的输入序列,合法的输出序列数为卡特兰数 (Catalan Number):
Cn=1n+1(2nn)C_n = \frac{1}{n+1} \binom{2n}{n}Cn=n+11(n2n)

例如,n=3n=3n=3 时合法的序列有 5 种。

6)实际应用场景

  1. 函数调用栈:程序执行时函数的调用和返回顺序必须符合栈的逻辑。
  2. 表达式求值:中缀表达式转后缀表达式时需处理运算符的优先级和结合性。
  3. 浏览器历史:页面的前进和后退操作类似栈的压入和弹出。

通过模拟栈的操作和验证输出序列的合法性,可以解决多数与栈顺序相关的问题。

2.原理:卡特兰数

1)卡特兰数的定义

卡特兰数(Catalan numbers)是组合数学中重要的数列,常用于解决计数问题。其第n项通常记作CnC_nCn,递推公式为:
Cn=1n+1(2nn) C_n = \frac{1}{n+1} \binom{2n}{n} Cn=n+11(n2n)

初始条件为C0=1C_0 = 1C0=1。前几项为:1, 1, 2, 5, 14, 42, 132...

2)递推关系

卡特兰数满足以下递推关系:
Cn=∑i=0n−1CiCn−1−i C_n = \sum_{i=0}^{n-1} C_i C_{n-1-i} Cn=i=0∑n−1CiCn−1−i

例如C4=C0C3+C1C2+C2C1+C3C0=1×5+1×2+2×1+5×1=14C_4 = C_0C_3 + C_1C_2 + C_2C_1 + C_3C_0 = 1×5 + 1×2 + 2×1 + 5×1 = 14C4=C0C3+C1C2+C2C1+C3C0=1×5+1×2+2×1+5×1=14。

3)常见应用场景

a.合法的括号序列

n对括号能组成CnC_nCn种合法的匹配序列。例如n=3时有5种:

①((())), ② (()()), ③(())(), ④()(()), ⑤()()()

b.二叉树形态计数

n个节点可以构成CnC_nCn种不同的满二叉树结构(每个节点有0或2个子节点)。

c.凸多边形三角划分

n+2边的凸多边形用不相交对角线划分为三角形,有CnC_nCn种方法。

d.不相交的弦

圆上2n个点两两连线不相交的方案数为CnC_nCn。

4)生成函数推导

卡特兰数的生成函数为:
G(x)=∑n=0∞Cnxn G(x) = \sum_{n=0}^\infty C_n x^n G(x)=n=0∑∞Cnxn

通过解方程G(x)=1+xG(x)2G(x) = 1 + xG(x)^2G(x)=1+xG(x)2,得到闭式:
G(x)=1−1−4x2x G(x) = \frac{1 - \sqrt{1-4x}}{2x} G(x)=2x1−1−4x

另一版本,可以直接计算卡特兰数:
Cn=1n+1(2nn)=(2n)!(n!)(n+1)!C_n = \frac{1}{n+1} \binom{2n}{n} = \frac{(2n)!}{(n!)(n+1)!}Cn=n+11(n2n)=(n!)(n+1)!(2n)!

5)实际计算示例

计算C4C_4C4:

  1. 组合数形式:15(84)=705=14\frac{1}{5}\binom{8}{4} = \frac{70}{5} = 1451(48)=570=14
  2. 递推方式:如前述C4=14C_4=14C4=14
  3. 直接公式:15×70=14\frac{1}{5}×70=1451×70=14

6)与其他数列关系

与二项式系数密切相关:
Cn=(2nn)−(2nn+1) C_n = \binom{2n}{n} - \binom{2n}{n+1} Cn=(n2n)−(n+12n)

这个差分形式体现了"合法路径"与"非法路径"的计数原理。

3.解析:逆波兰表达式

1)逆波兰表达式简介

逆波兰表达式 (Reverse Polish Notation,RPN)是一种数学表达式的书写方法,其特点是将运算符写在操作数的后面。例如,常见的表达式 (1 + 2) * 3 在逆波兰表达式中写为 1 2 + 3 *。这种表示法无需括号即可明确运算顺序,适合栈结构处理。

2)逆波兰表达式的求值步骤

  1. 初始化栈

    使用一个栈存储操作数,遍历逆波兰表达式的每个元素。

  2. 处理操作数

    当遇到数字时,将其压入栈中。

  3. 处理运算符

    当遇到运算符时,从栈顶弹出两个操作数进行计算,并将结果压回栈中。注意操作数的顺序(先弹出的是右操作数)。

  4. 最终结果

    遍历结束后,栈顶元素即为表达式的结果。

3)示例代码实现

以下是逆波兰表达式求值的 Python 实现:

python 复制代码
def eval_rpn(tokens):
    stack = []
    for token in tokens:
        if token in "+-*/":
            b = stack.pop()
            a = stack.pop()
            if token == '+':
                stack.append(a + b)
            elif token == '-':
                stack.append(a - b)
            elif token == '*':
                stack.append(a * b)
            elif token == '/':
                stack.append(int(a / b))  # 注意除法向零取整
        else:
            stack.append(int(token))
    return stack.pop()

示例解析

以逆波兰表达式 ["2", "1", "+", "3", "*"] 为例:

  • 遍历 "2""1",压入栈中 → 栈:[2, 1]
  • 遇到 "+",弹出 12,计算 2 + 1 = 3,压入栈 → 栈:[3]
  • 遍历 "3",压入栈 → 栈:[3, 3]
  • 遇到 "*",弹出 33,计算 3 * 3 = 9,压入栈 → 栈:[9]
  • 最终结果为 9

注意事项

  • 除法处理 :逆波兰表达式的除法需向零取整(如 6 / -4 = -1)。
  • 操作数顺序 :减法和除法需注意操作数的顺序(如 a - ba / b)。
  • 有效性验证:输入需确保是合法的逆波兰表达式(操作数与运算符匹配)。
相关推荐
天若有情6732 小时前
Multi-Stride Predictive RNG:革命性的可控随机数生成算法
算法·算法设计·c++编程·随机数生成·msp-rng·魔术算法
guguhaohao2 小时前
map和set,咕咕咕!
数据结构·c++
C_Liu_2 小时前
14:C++:二叉搜索树
算法
white-persist2 小时前
汇编代码详细解释:汇编语言如何转化为对应的C语言,怎么转化为对应的C代码?
java·c语言·前端·网络·汇编·安全·网络安全
CC-NX2 小时前
32位汇编:实验9分支程序结构使用
汇编·算法·win32·分支结构
Larry_Yanan2 小时前
QML学习笔记(五十二)QML与C++交互:数据转换——时间和日期
开发语言·c++·笔记·qt·学习·ui·交互
万岳科技系统开发2 小时前
外卖小程序中的高并发处理:如何应对大流量订单的挑战
算法·小程序·开源
TL滕2 小时前
从0开始学算法——第二天(时间、空间复杂度)
数据结构·笔记·学习·算法
C++chaofan3 小时前
MyBatis - Plus学习笔记
java·spring boot·笔记·后端·mysql·架构·mybatis