棧(LIFO)與隊列(FIFO)是最基礎的線性數據結構。本文詳細講解其定義、順序/鏈式兩種實現方式、核心操作代碼,重點分析循環隊列解決假溢出的原理與環形緩衝區優化技巧,並提供完整 Java 實現源碼鏈接。
push(入棧)、pop(出棧)、top(棧頂指針)// 入棧
public void push(T item) {
if (top >= capacity) throw new IllegalStateException("Stack full");
items[top++] = item;
}
// 出棧
public T pop() {
if (top <= 0) return null;
return (T) items[--top];
}
private class Node { T item; Node next; }
private Node top; int count;
// 入棧:頭插法
public void push(T item) {
Node old = top;
top = new Node();
top.item = item;
top.next = old;
count++;
}
// 出棧:移動 top 指針
public T pop() {
T item = top.item;
top = top.next;
count--;
return item;
}
head(讀)、tail(寫)數組實現時,tail == maxSize 不代表隊列滿,可能 head 前有空閒空間(假溢出)。
邏輯上將數組首尾相連,指針取模運算實現循環:
// 取模版本 head = (head + 1) % maxSize; tail = (tail + 1) % maxSize; size = (tail + maxSize - head) % maxSize; // 無取模優化版(RingBuffer 風格) int next = tail + 1; if (next >= bufferSize) next = 0; if (next == head) return false; // 滿 buffer[next] = item; tail = next;
private Node head, tail;
// 入隊:尾部掛接
public void enqueue(T item) {
Node old = tail;
tail = new Node();
tail.item = item;
tail.next = null;
if (isEmpty()) head = tail;
else old.next = tail;
count++;
}
// 出隊:頭部移動
public T dequeue() {
T res = head.item;
head = head.next;
if (isEmpty()) tail = null;
count--;
return res;
}
完整可運行實現:GitHub 算法倉庫