繼靜態陣列、動態陣列實現堆疊後,本文介紹帶頭結點單鏈表實現。鏈表無固定容量限制,且堆疊的「先進後出」特性與單鏈表「頭部插入/刪除 O(1)」完美契合。
typedef int ElemType;
typedef struct Node {
ElemType data;
struct Node *next;
} Node, *Stack; // Stack 即為指向頭結點的指標
頭結點不存放資料,next 指向棧頂元素。空堆疊時 head->next == NULL。
void createStack(Stack *s) {
*s = (Stack)malloc(sizeof(Node));
if (!*s) { fprintf(stderr, "記憶體配置失敗\n"); exit(1); }
(*s)->next = NULL;
}
void push(Stack s, ElemType val) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) { fprintf(stderr, "記憶體配置失敗\n"); return; }
newNode->data = val;
newNode->next = s->next; // 新節點指向原棧頂
s->next = newNode; // 頭結點指向新棧頂
}
void pop(Stack s) {
if (isEmpty(s)) return;
Node *topNode = s->next;
s->next = topNode->next;
free(topNode);
}
void top(Stack s) {
if (isEmpty(s)) { printf("堆疊為空\n"); return; }
printf("棧頂元素:%d\n", s->next->data);
}
int isEmpty(Stack s) {
return s->next == NULL;
}
void printStack(Stack s) {
if (isEmpty(s)) { printf("堆疊為空\n"); return; }
Node *p = s->next;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
void destroyStack(Stack s) {
Node *p = s->next;
while (p) {
Node *tmp = p;
p = p->next;
free(tmp);
}
s->next = NULL;
}
int main() {
Stack s;
createStack(&s);
push(s, 3); push(s, 1); push(s, 9); push(s, 4); push(s, 7);
printStack(s); // 7 4 9 1 3
pop(s); pop(s);
printStack(s); // 9 1 3
top(s); // 9
destroyStack(s);
printStack(s); // 堆疊為空
return 0;
}
| 特性 | 靜態陣列 | 動態陣列 | 單鏈表(帶頭結點) |
|---|---|---|---|
| 容量 | 固定 | 可擴容 | 無上限(受限於記憶體) |
| 入棧/出棧 | O(1) | 均攤 O(1) | O(1) |
| 記憶體碎片 | 無 | 少 | 較多 |
| 快取友好 | 最佳 | 良好 | 較差 |
| 實現複雜度 | 最低 | 中等 | 較高 |
malloc 必須配對 free,避免洩漏new->next = head->next 再 head->next = new;出棧先保存 top 再 head->next = top->next 最後 free(top)malloc 失敗、空堆疊操作均需檢查原始碼已上傳 GitHub:Stack_LinkedList