📜  Python堆栈(1)

📅  最后修改于: 2023-12-03 15:34:28.197000             🧑  作者: Mango

Python堆栈

什么是堆栈

堆栈是一种“后进先出”(LIFO)的数据结构,也被称为“先进后出”(FILO)的数据结构。这意味着最后一个添加到堆栈中的元素是第一个被删除的元素。堆栈是一个很好的选择,当你需要一个严格的顺序执行的方法集,或者你需要一种简单的方法来跟踪从过程中发生的操作。

在Python中,我们可以使用列表来实现堆栈。当然,我们可以使用collections.deque等数据类型,这里选取列表介绍

堆栈的实现
stack = []

# 入栈
stack.append(1)
stack.append(2)
stack.append(3)

# 出栈
stack.pop()

在代码中,我们用一个列表来存储堆栈中的元素。使用append()方法来添加元素到堆栈中,使用pop()方法来移除并返回堆栈顶部的元素。

堆栈的应用

堆栈的应用非常广泛,比如:

  1. 实现表达式计算
  2. 实现函数调用过程中的参数传递和调用回溯
  3. 实现撤销/恢复操作
实现表达式计算

我们可以使用堆栈来实现表达式计算。对于一个算术表达式,我们可以使用两个堆栈,一个用来存储操作数,一个用来存储操作符。对于每一个新进来的操作符,我们需要判断其优先级和前一个操作符的优先级来决定是否需要进行运算。

def evaluate(expression:str)->int:
    # 操作数栈
    operands = []
    # 操作符栈
    operators = []
    # 运算符优先级
    precedence = {"+": 1, "-": 1, "*": 2, "/": 2, "^": 3}

    # 将中缀表达式转换为后缀表达式
    for token in expression:
        if token.isdigit():
            # 操作数
            operands.append(int(token))
        elif token in precedence.keys():
            # 操作符
            while operators and operators[-1] != "(" and precedence[token] <= precedence[operators[-1]]:
                operands.append(do_math(operators.pop(), operands.pop(), operands.pop()))
            operators.append(token)
        elif token == "(":
            operators.append(token)
        elif token == ")":
            while operators[-1] != "(":
                operands.append(do_math(operators.pop(), operands.pop(), operands.pop()))
            operators.pop()

    while operators:
        operands.append(do_math(operators.pop(), operands.pop(), operands.pop()))

    return operands.pop()

def do_math(op, op1, op2):
    if op == "+":
        return op2 + op1
    elif op == "-":
        return op2 - op1
    elif op == "*":
        return op2 * op1
    elif op == "/":
        return op2 / op1
    elif op == "^":
        return op2 ** op1
实现函数调用过程中的参数传递和调用回溯

在函数调用过程中,我们可以使用堆栈来实现参数传递和调用回溯。具体来说,每当我们调用一个函数,就将函数名和参数压入堆栈中;当函数返回时,则将返回值压入堆栈中。

def foo(x):
    return x + 1

def bar(y):
    return y * 2

# 调用栈
stack = []

# 调用函数foo
stack.append(("foo", 1))
# 调用函数bar
stack.append(("bar", foo(stack[-1][1])))

# 回溯调用栈,获取返回值
result = stack.pop()[1]
result = stack.pop()[1]

print(result)    # 输出2

在代码中,我们使用一个元组来表示函数名和参数,并将其压入堆栈中。在返回时,我们取出返回值,并回溯调用栈以获取上一级函数的返回值。

实现撤销/恢复操作

我们可以使用堆栈来实现撤销/恢复操作。当用户执行撤销操作时,我们将当前状态压入堆栈中;当用户执行恢复操作时,则从堆栈中取出最后一个状态,并将其作为当前状态。

# 状态堆栈
state_stack = []

# 初始状态
state = {"x": 0, "y": 0}
print(state)

# 执行操作1
state["x"] += 1
print(state)
# 将操作1的状态压入堆栈
state_stack.append(state.copy())

# 执行操作2
state["y"] += 1
print(state)
# 将操作2的状态压入堆栈
state_stack.append(state.copy())

# 撤销操作2
state = state_stack.pop()
print(state)

# 恢复操作2
state = state_stack.pop()
print(state)

在代码中,我们使用一个字典来表示状态,当用户执行操作时,我们将当前状态压入堆栈中。当用户执行撤销操作时,我们从堆栈中取出最后一个状态;当用户执行恢复操作时,则从堆栈中取出倒数第二个状态。