堆疊是資料結構中基礎且重要的一環,遵循「後進先出」(LIFO, Last In First Out)原則,常用於實現遞迴、運算式求值、瀏覽器歷史記錄等場景。本文將帶領讀者從零開始,使用 Java 實作一個功能完整的整數堆疊,並深入解析核心邏輯。
一個標準的堆疊主要包含三個核心操作:
以下是一個固定容量的整數堆疊實作 ToyStack,包含邊界檢查與異常處理:
/**
* 簡易整數堆疊實作
*/
public class ToyStack {
/** 堆疊最大深度 */
protected int MAX_DEPTH = 10;
/** 目前堆疊深度 */
protected int depth = 0;
/** 底層儲存陣列 */
protected int[] stack = new int[MAX_DEPTH];
/**
* 推入元素
* @param n 待推入的整數
* @throws RuntimeException 當堆疊已滿時拋出
*/
protected void push(int n) {
if (depth == MAX_DEPTH - 1) {
throw new RuntimeException("堆疊已滿,無法再添加元素。");
}
stack[depth++] = n;
}
/**
* 彈出頂端元素
* @return 頂端元素值
* @throws RuntimeException 當堆疊為空時拋出
*/
protected int pop() {
if (depth == 0) {
throw new RuntimeException("堆疊中元素已被取完,無法再取。");
}
// 先遞減 depth,再取值,相當於刪除頂端元素
return stack[--depth];
}
/**
* 窺視頂端元素但不移除
* @return 頂端元素值
* @throws RuntimeException 當堆疊為空時拋出
*/
protected int peek() {
if (depth == 0) {
throw new RuntimeException("堆疊中元素已被取完,無法再取。");
}
return stack[depth - 1];
}
}
使用 int[] stack 作為靜態儲存空間,depth 變數同時扮演「目前元素數量」與「下一個可寫入索引」的雙重角色。這是陣列實作堆疊最經典的模式。
pop() 中的前置遞減 --depthreturn stack[--depth]; 這行程式碼精妙地完成了兩件事:將指標向下移一格(邏輯上移除頂端元素),並返回新指標位置的值。若改用 depth-- 會導致索引越界或返回錯誤值。
在 push、pop、peek 中均檢查邊界條件(滿/空),並拋出 RuntimeException。這比返回特殊值(如 -1)更安全,避免呼叫端忽略錯誤狀態。
此實作為教學示範,實務上可考慮以下增強:
ArrayList 或動態陣列擴容,移除固定容量限制。<T> 支援任意物件類型(參見進階版實作)。Iterable 介面,支援增強型 for 迴圈遍歷。size()、isEmpty()、clear() 等輔助方法。掌握堆疊實作細節,不僅能深化對資料結構的理解,更是面試與系統設計的必備基本功。