
栈(Stack)是一种特殊的线性数据结构,遵循后进先出(Last In First Out,LIFO)的原则。这就好比一摞盘子,最后放上去的盘子总是最先被拿走。栈有两个主要的操作:入栈(Push)和出栈(Pop)。入栈是将元素添加到栈的顶部,而出栈则是从栈的顶部移除元素。此外,还有一个查看栈顶元素的操作叫做 peek。
顺序栈使用数组来实现栈的功能。通过一个指针(通常称为栈顶指针)来记录栈顶元素的位置。当进行入栈操作时,栈顶指针向上移动;出栈操作时,栈顶指针向下移动。
class SeqStack:def __init__(self, max_size=100):# 初始化栈,使用列表存储元素self.max_size = max_sizeself.stack = [None] * max_sizeself.top = -1def is_empty(self):# 判断栈是否为空return self.top == -1def is_full(self):# 判断栈是否已满return self.top == self.max_size - 1def push(self, item):# 入栈操作if self.is_full():print("Stack is full")returnself.top += 1self.stack[self.top] = itemdef pop(self):# 出栈操作if self.is_empty():print("Stack is empty")return Noneitem = self.stack[self.top]self.top -= 1return itemdef peek(self):# 查看栈顶元素if self.is_empty():print("Stack is empty")return Nonereturn self.stack[self.top]# 测试顺序栈stack = SeqStack()stack.push(1)stack.push(2)stack.push(3)print(stack.pop()) # 输出 3print(stack.peek()) # 输出 2
| 优点 | 缺点 |
|---|---|
| 实现简单,使用数组存储元素,访问速度快 | 栈的大小在初始化时确定,可能会造成空间浪费或不足 |
链式栈使用链表来实现栈的功能。链表的每个节点包含一个数据元素和一个指向下一个节点的指针。栈顶元素位于链表的头部,入栈操作相当于在链表头部插入一个新节点,出栈操作相当于删除链表头部的节点。
class Node:def __init__(self, data):# 初始化节点,包含数据和指向下一个节点的指针self.data = dataself.next = Noneclass LinkedStack:def __init__(self):# 初始化栈,栈顶指针初始化为 Noneself.top = Nonedef is_empty(self):# 判断栈是否为空return self.top is Nonedef push(self, item):# 入栈操作new_node = Node(item)new_node.next = self.topself.top = new_nodedef pop(self):# 出栈操作if self.is_empty():print("Stack is empty")return Noneitem = self.top.dataself.top = self.top.nextreturn itemdef peek(self):# 查看栈顶元素if self.is_empty():print("Stack is empty")return Nonereturn self.top.data# 测试链式栈stack = LinkedStack()stack.push(1)stack.push(2)stack.push(3)print(stack.pop()) # 输出 3print(stack.peek()) # 输出 2
| 优点 | 缺点 |
|---|---|
| 栈的大小可以动态调整,不会造成空间浪费 | 每个节点需要额外的指针域,增加了空间开销;链表节点的内存地址不连续,访问速度相对较慢 |
栈是一种非常重要的数据结构,顺序栈和链式栈是栈的两种常见实现方式。通过了解它们的原理、优缺点和适用场景,我们可以根据具体的需求选择合适的实现方式。