深入理解堆栈数据结构及其应用
堆栈的基本概念与特性
堆栈(Stack)是一种非常重要的线性数据结构,它遵循"后进先出"(Last In First Out,LIFO)的原则。这意味着最后进入堆栈的元素会最先被取出,就像我们日常生活中叠放的盘子,总是先取用最上面的那个。
堆栈有两个主要端点:
- 栈顶(Top):允许进行插入和删除操作的一端
- 栈底(Bottom):不允许进行操作的另一端
堆栈的基本操作包括:
- Push(入栈):在栈顶添加一个新元素
- Pop(出栈):移除并返回栈顶元素
- Peek/Top(查看栈顶):返回栈顶元素但不移除它
- isEmpty(判空):检查堆栈是否为空
- isFull(判满):检查堆栈是否已满(仅顺序存储时需要)
堆栈的两种实现方式
顺序栈实现
顺序栈使用数组作为底层存储结构,具有连续的内存空间。它的特点是实现简单、访问速度快,但大小固定,不够灵活。
class Stack:
def __init__(self, size=100):
self.stack = []
self.size = size
self.top = -1
def is_empty(self):
return self.top == -1
def is_full(self):
return self.top + 1 == self.size
def push(self, value):
if self.is_full():
raise Exception('Stack is full')
self.stack.append(value)
self.top += 1
def pop(self):
if self.is_empty():
raise Exception('Stack is empty')
self.top -= 1
return self.stack.pop()
def peek(self):
if self.is_empty():
raise Exception('Stack is empty')
return self.stack[self.top]
链式栈实现
链式栈使用链表作为底层存储结构,每个节点包含数据和指向下一个节点的指针。它的特点是大小动态可变,但实现稍复杂,访问速度相对较慢。
class Node:
def __init__(self, value):
self.value = value
self.next = None
class Stack:
def __init__(self):
self.top = None
def is_empty(self):
return self.top is None
def push(self, value):
new_node = Node(value)
new_node.next = self.top
self.top = new_node
def pop(self):
if self.is_empty():
raise Exception('Stack is empty')
temp = self.top
self.top = self.top.next
return temp.value
def peek(self):
if self.is_empty():
raise Exception('Stack is empty')
return self.top.value
堆栈的典型应用场景
1. 括号匹配问题
这是一个经典的堆栈应用场景,用于检查表达式中的括号是否正确配对。
算法思路:
- 遍历字符串中的每个字符
- 遇到左括号时入栈
- 遇到右括号时检查栈顶元素是否匹配
- 最后检查栈是否为空
def is_valid(s: str) -> bool:
if len(s) % 2 != 0:
return False
stack = []
mapping = {')': '(', ']': '[', '}': '{'}
for char in s:
if char in mapping.values():
stack.append(char)
elif char in mapping.keys():
if not stack or mapping[char] != stack.pop():
return False
else:
return False
return not stack
2. 表达式求值问题
堆栈可以用于计算数学表达式,特别是处理运算符优先级的问题。
算法思路:
- 使用两个栈分别存储数字和运算符
- 根据运算符优先级决定计算顺序
- 遇到高优先级运算符时立即计算
- 最后按顺序计算剩余运算
def calculate(s: str) -> int:
stack = []
num = 0
sign = '+'
for i, char in enumerate(s):
if char.isdigit():
num = num * 10 + int(char)
if (not char.isdigit() and char != ' ') or i == len(s) - 1:
if sign == '+':
stack.append(num)
elif sign == '-':
stack.append(-num)
elif sign == '*':
stack.append(stack.pop() * num)
elif sign == '/':
stack.append(int(stack.pop() / num))
sign = char
num = 0
return sum(stack)
堆栈的其他应用
除了上述经典问题外,堆栈还有许多其他重要应用:
- 函数调用栈:程序执行时的函数调用关系就是通过堆栈来管理的
- 浏览器历史记录:前进后退功能就是基于堆栈实现的
- 撤销操作:许多软件的撤销功能使用堆栈记录操作历史
- 深度优先搜索:图的DFS算法通常使用堆栈来实现
- 递归转迭代:递归算法可以转换为使用堆栈的迭代算法
总结
堆栈作为一种基础而重要的数据结构,在算法和系统设计中有着广泛的应用。理解堆栈的工作原理和实现方式,掌握其典型应用场景,对于提高编程能力和解决实际问题都有很大帮助。通过顺序栈和链式栈的不同实现,我们可以根据具体场景选择最适合的存储方式。在实际应用中,堆栈往往能提供简洁高效的解决方案。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考