lec3 List Stack Queue(2)
lec3 List Stack Queue(2)
关于链表,栈,队列。
列表抽象数据类型(Stack ADT)
栈的重点在于应用,其他一带而过即可。
Stack (栈)
栈(Stack)是一种数据结构,允许我们只在其一端进行插入(Push)和删除(Pop)操作。这个端口被称为栈的顶部(Top)。栈遵循 LIFO(Last In, First Out,后进先出)原则,即最后插入的元素最先被删除。
栈的基本操作:
- Push:将元素插入到栈的顶部。
- Pop:删除并返回栈顶元素(也称为 TopAndPop)。
- IsEmpty:测试栈是否为空。
- Peek(或Top):查看栈顶元素,但不移除它(有时也包括在栈的实现中)。
栈的实现方式:
栈可以通过不同的数据结构来实现,常见的实现方式有 链表实现 和 数组实现。
Stack ADT(抽象数据类型)
栈(Stack)是一个具有 后进先出(LIFO, Last In, First Out)特性的线性数据结构,通常提供三种基本操作:插入(Push)、删除(Pop)和查看栈顶元素(Top)。为了确保栈的操作具有一致性和可扩展性,可以使用抽象数据类型(ADT)来定义栈的接口。
栈的抽象数据类型通过接口定义了栈应当支持的操作,包括对栈的插入、删除以及查看栈顶元素等功能。
1 | // The Stack ADT |
数组实现栈(Array-Based Stack):
在数组实现的栈中,栈的大小是固定的,因此栈必须在初始化时指定容量。栈的操作比较简单,所有的元素都存储在一个数组中,栈顶的元素通过一个索引进行标记。
数组栈的特性:
- 固定大小:栈的最大大小在创建时定义,后续无法动态扩展(除非进行特殊处理,如扩容)。
- 简化的数组列表:栈操作通常是在数组的尾部进行,类似于一个队列的尾端插入和删除。
AStack 类的实现:
1 | template <typename E> |
栈操作的工作原理:
- Push 操作:
- 在执行 Push 操作时,首先检查栈是否已满(通过
top
与maxSize
比较),如果栈满则抛出异常。 - 然后,将元素
it
放入当前栈顶的位置,并更新栈顶指针top
(top++
)。
- 在执行 Push 操作时,首先检查栈是否已满(通过
- Pop 操作:
- 在执行 Pop 操作时,首先检查栈是否为空(通过
top
与 0 比较),如果栈空则抛出异常。 - 然后,更新栈顶指针
top
(top--
),并返回被删除的栈顶元素。
- 在执行 Pop 操作时,首先检查栈是否为空(通过
- TopValue 操作:
- TopValue 操作返回栈顶元素的引用,但不删除栈顶元素。
- 如果栈为空,调用该方法将抛出异常。
- Clear 操作:
- Clear 操作将栈重新初始化,即将栈顶指针
top
重置为 0,表示栈为空。
- Clear 操作将栈重新初始化,即将栈顶指针
时间复杂度分析:
- Push 操作:O(1),将元素插入栈顶是常数时间操作。
- Pop 操作:O(1),移除栈顶元素是常数时间操作。
- TopValue 操作:O(1),查看栈顶元素是常数时间操作。
- Clear 操作:O(1),重置栈顶指针为 0,也是常数时间操作。
Linked Stack(链式栈)
链式栈(Linked Stack)是栈的一种实现方式,与数组实现的栈不同,链式栈基于链表的结构来动态管理栈的元素。链式栈的优势在于其动态性,能够随着元素的增加或减少灵活调整栈的大小,而不需要提前指定栈的容量。
链式栈(Linked Stack)的基本结构和操作:
链式栈的元素通常是通过链表节点(Link)来表示的,栈的每个节点包含两个部分:
- 元素数据(element):存储栈中的数据。
- 指向下一个节点的指针(next):指向链表中的下一个节点。
栈的顶端由 top 指针表示,初始时 top
为 NULL
,表示栈为空。
LStack 类的实现:
下面是链式栈的实现代码:
1 | // 链式栈的实现 |
栈操作的实现细节:
构造函数(
LStack
):- 初始化时,栈为空,
top
指针指向NULL
,size
初始化为 0。
- 初始化时,栈为空,
清空栈(
clear
):- 通过循环遍历栈中的每个节点,逐个删除。
- 通过
top
指针逐步移动到下一个节点,释放当前节点的内存。
Push 操作(
push
):- 在链式栈中,
push
操作通过创建一个新节点,将栈顶指针指向新节点,并将新节点的next
指针指向原来的栈顶(即原来的节点)。 - 新节点成为栈的栈顶,栈大小
size
增加。
1
top = new Link<E>(it, top);
- 在链式栈中,
Pop 操作(
pop
):pop
操作会首先获取栈顶元素的值,然后将栈顶指针top
更新为指向下一个节点(即删除当前栈顶节点)。- 被删除的节点会被释放内存,并返回栈顶元素的值。
1
2
3
4E it = top->element;
Link<E>* ltemp = top->next;
delete top;
top = ltemp;TopValue 操作(
topValue
):- 返回栈顶元素的副本,但不会修改栈顶指针。
- 如果栈为空,调用该方法会抛出异常。
1
return top->element;
时间复杂度分析:
- Push 操作:O(1),每次将新节点插入栈顶。
- Pop 操作:O(1),每次删除栈顶节点。
- TopValue 操作:O(1),直接返回栈顶元素。
- Clear 操作:O(n),需要遍历整个链表并删除所有节点。
数组栈与链栈的比较:实现、时间复杂度与空间复杂度
时间和空间复杂度总结:
操作 | 数组栈 | 链栈 |
---|---|---|
Push | O(1) | O(1) |
Pop | O(1) | O(1) |
TopValue | O(1) | O(1) |
Clear | O(1) | O(n) |
空间复杂度 | O(n) | O(n) + O(n)(指针开销) |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Totoroの旅!
评论