栈是一种重要的线性数据结构,它遵循后进先出(LIFO, Last In First Out)的原则。下面我将全面介绍栈的相关知识。
一、栈的基本概念
1. 栈的定义
栈是限定仅在表尾进行插入和删除操作的线性表。允许插入和删除的一端称为栈顶(Top),另一端称为栈底(Bottom)。
2. 栈的特性
-
后进先出(LIFO)原则
-
只能在栈顶进行操作
-
插入操作称为入栈(Push)
-
删除操作称为出栈(Pop)
二、栈的基本操作
栈通常支持以下基本操作:
-
push(x)
- 将元素x压入栈顶 -
pop()
- 弹出栈顶元素 -
peek()
/top()
- 获取栈顶元素但不弹出 -
isEmpty()
- 判断栈是否为空 -
size()
- 获取栈中元素数量
三、栈的实现方式
1. 基于数组的实现
class ArrayStack:
def __init__(self):
self._data = []
def push(self, item):
self._data.append(item)
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._data.pop()
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._data[-1]
def is_empty(self):
return len(self._data) == 0
def size(self):
return len(self._data)
2. 基于链表的实现
class LinkedStack:
class _Node:
__slots__ = '_element', '_next'
def __init__(self, element, next):
self._element = element
self._next = next
def __init__(self):
self._head = None
self._size = 0
def push(self, item):
self._head = self._Node(item, self._head)
self._size += 1
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
answer = self._head._element
self._head = self._head._next
self._size -= 1
return answer
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._head._element
def is_empty(self):
return self._size == 0
def size(self):
return self._size
四、栈的应用场景
-
函数调用栈:程序执行时函数调用和返回的机制
-
表达式求值:中缀表达式转后缀表达式,以及后缀表达式的计算
-
括号匹配:检查代码中的括号是否成对出现
-
浏览器前进后退:使用两个栈实现
-
撤销操作(Undo):许多软件的撤销功能
-
深度优先搜索(DFS):图算法中使用栈实现
五、栈的经典算法问题
-
有效的括号:检查字符串中的括号是否有效匹配
-
最小栈:设计一个能在O(1)时间内获取最小元素的栈
-
用栈实现队列:使用栈模拟队列的操作
-
逆波兰表达式求值:计算后缀表达式的值
-
柱状图中最大矩形:利用栈解决最大矩形面积问题
六、栈的时间复杂度分析
操作 | 时间复杂度 |
---|---|
push() | O(1) |
pop() | O(1) |
peek() | O(1) |
isEmpty() | O(1) |
size() | O(1) |
七、学习建议
-
理解栈的LIFO特性
-
掌握栈的基本操作实现
-
多做相关算法题加深理解
-
思考栈在实际应用中的使用场景
-
比较栈与队列等其他数据结构的异同