堆疊幾乎是程式設計的命脈,沒有堆疊就沒有函式呼叫,自然也就沒有軟體架構。作為一種「先進後出」的資料結構,堆疊的長度取決於堆疊頂端的高度。本文將帶領讀者從零開始,使用 C 語言實作一個基於連續記憶體的線性堆疊,涵蓋節點設計、建立、釋放、壓入、彈出與統計等核心操作。
首先定義堆疊節點結構 STACK_NODE,包含三個關鍵欄位:
int* pData:指向動態分配的整數陣列,儲存實際資料int length:堆疊的最大容量int top:堆疊頂端索引,同時也代表目前元素個數typedef struct _STACK_NODE {
int* pData;
int length;
int top;
} STACK_NODE;
alloca_stack 函式根據指定容量分配記憶體,並完成初始化:
STACK_NODE* alloca_stack(int number) {
if (0 == number) return NULL;
STACK_NODE* pStackNode = (STACK_NODE*)malloc(sizeof(STACK_NODE));
assert(NULL != pStackNode);
memset(pStackNode, 0, sizeof(STACK_NODE));
pStackNode->pData = (int*)malloc(sizeof(int) * number);
if (NULL == pStackNode->pData) {
free(pStackNode);
return NULL;
}
memset(pStackNode->pData, 0, sizeof(int) * number);
pStackNode->length = number;
pStackNode->top = 0;
return pStackNode;
}
關鍵點:雙重 malloc 分別分配結構體與資料陣列,失敗時需釋放已分配記憶體防止洩漏。
free_stack 依序釋放資料陣列與結構體本身:
STATUS free_stack(const STACK_NODE* pStackNode) {
if (NULL == pStackNode) return FALSE;
assert(NULL != pStackNode->pData);
free(pStackNode->pData);
free((void*)pStackNode);
return TRUE;
}
檢查堆疊是否已滿,若未滿則在 top 位置寫入並遞增:
STATUS stack_push(STACK_NODE* pStackNode, int value) {
if (NULL == pStackNode) return FALSE;
if (pStackNode->length == pStackNode->top) return FALSE; // 滿了
pStackNode->pData[pStackNode->top++] = value;
return TRUE;
}
注意:原始碼中 if(pStackNode->length = pStackNode->top) 為賦值而非比較,此處已修正為 ==。
檢查堆疊是否為空,若非空則遞減 top 並取出值:
STATUS stack_pop(STACK_NODE* pStackNode, int* value) {
if (NULL == pStackNode || NULL == value) return FALSE;
if (0 == pStackNode->top) return FALSE; // 空了
*value = pStackNode->pData[--pStackNode->top];
return TRUE;
}
直接回傳 top 即可,因為 top 恰好等於有效元素個數:
int count_stack_number(const STACK_NODE* pStackNode) {
return pStackNode->top;
}
堆疊是函式呼叫、遞迴實作的基石。建議開發者動手實作並測試邊界條件(滿、空、單元素),深入理解其運作機制,這對掌握更複雜的資料結構與演算法大有裨益。