Update 算法 - 栈和队列.md

补充动态数组栈缩容防抖动的说明,调整链表栈与链表队列关于指针方向选取的说明及复杂度分析。
This commit is contained in:
CyC2018
2026-10-30 20:19:20 +08:00
parent 260f525ed4
commit 91d3c02c9c
+4 -2
View File
@@ -27,6 +27,8 @@ public interface MyStack<Item> extends Iterable<Item> {
### 1. 数组实现
数组满时容量翻倍,元素数量降到容量的 1/4 时容量减半。不在半满时就减半,是为了避免抖动:例如容量为 4 且已满时 push 一次,扩容到 8;如果半满就减半,接着 pop 一次,元素回到 4 个,又缩回 4。之后交替 push 和 pop,每次操作都要复制全部元素。
```java
public class ArrayStack<Item> implements MyStack<Item> {
@@ -126,7 +128,7 @@ public class ArrayStack<Item> implements MyStack<Item> {
### 2. 链表实现
需要使用链表的头插法来实现,因为头插法中最后压入栈的元素在链表的开头,它的 next 指针指向前一个压入栈的元素,在弹出元素时就可以通过 next 指针遍历到前一个压入栈的元素从而让这个元素成为新的栈顶元素。
栈顶放在链表头部,使用头插法:push 时新节点的 next 指向原来的栈顶,pop 时栈顶移到 next 指向的节点,两个操作都是 O(1)。如果栈顶放在链表尾部,pop 时需要找到尾节点的前一个节点,单链表只能从头遍历。
```java
public class ListStack<Item> implements MyStack<Item> {
@@ -215,7 +217,7 @@ public class ListStack<Item> implements MyStack<Item> {
下面是队列的链表实现,需要维护 first 和 last 节点指针,分别指向队首和队尾。
这里需要考虑 first 和 last 指针哪个作为链表的开头。因为出队列操作需要让队首元素的下一个元素成为队首,所以需要容易获取下一个元素,而链表的头部节点的 next 指针指向下一个元素,因此可以让 first 指针指向链表的开头。
队首放在链表头部,队尾放在链表尾部:入队时在 last 后面追加,出队时 first 移到 next 指向的节点,两个操作都是 O(1)。如果反过来,出队要删除尾节点,需要找到它的前一个节点,单链表只能从头遍历。
```java
public interface MyQueue<Item> extends Iterable<Item> {