帶頭結點單鏈表將「空表判斷」、「首節點操作」等邊界條件統一化,是數據結構教學與工程實踐的首選。本文提供 13 個核心操作的完整、可編譯運行的 C 語言實現,涵蓋初始化、創建、遍歷、增刪改查、清空等全生命周期。
typedef int elemType;
typedef struct Node {
elemType element;
struct Node *next;
} Node;
InitialListvoid InitialList(Node **head) {
*head = (Node*)malloc(sizeof(Node));
if (!*head) { perror("malloc"); exit(1); }
(*head)->next = NULL;
}
CreateListvoid CreateList(Node *head) {
Node *pInsert, *pMove = head;
pInsert = (Node*)malloc(sizeof(Node));
pInsert->next = NULL;
scanf("%d", &pInsert->element);
while (pInsert->element > 0) {
pMove->next = pInsert;
pMove = pInsert;
pInsert = (Node*)malloc(sizeof(Node));
pInsert->next = NULL;
scanf("%d", &pInsert->element);
}
free(pInsert);
}
PrintListvoid PrintList(Node *head) {
Node *p = head->next;
while (p) { printf("%d ", p->element); p = p->next; }
printf("\n");
}
ClearList (保留頭結點)void ClearList(Node *head) {
Node *p = head->next;
while (p) {
head->next = p->next;
free(p);
p = head->next;
}
}
SizeListint SizeList(Node *head) {
int n = 0;
for (Node *p = head->next; p; p = p->next) n++;
return n;
}
IsEmptyListint IsEmptyList(Node *head) { return head->next == NULL; }
GetElement (1-based)int GetElement(Node *head, int pos) {
Node *p = head->next;
for (int i = 1; p && i < pos; i++) p = p->next;
return p ? p->element : -1;
}
GetElemAddrelemType* GetElemAddr(Node *head, int x) {
for (Node *p = head->next; p; p = p->next)
if (p->element == x) return &p->element;
return NULL;
}
ModifyElemNode* ModifyElem(Node *head, int pos, int x) {
Node *p = head->next;
for (int i = 1; p && i < pos; i++) p = p->next;
if (p) p->element = x;
return head;
}
InsertHeadListNode* InsertHeadList(Node *head, int x) {
Node *n = (Node*)malloc(sizeof(Node));
n->element = x;
n->next = head->next;
head->next = n;
return head;
}
InsertTailListNode* InsertTailList(Node *head, int x) {
Node *n = (Node*)malloc(sizeof(Node));
n->element = x; n->next = NULL;
Node *p = head;
while (p->next) p = p->next;
p->next = n;
return head;
}
InsertNode (pos 從 0 開始,頭結點後為 0)Node* InsertNode(Node *head, int pos, int x) {
Node *pre = head;
for (int i = 0; pre && i < pos; i++) pre = pre->next;
if (!pre) return head;
Node *n = (Node*)malloc(sizeof(Node));
n->element = x;
n->next = pre->next;
pre->next = n;
return head;
}
DeletePosNode / 按值刪除 DeleteValueNodeint main() {
Node *list; InitialList(&list);
CreateList(list); // 輸入: 10 20 30 0
PrintList(list); // 10 20 30
printf("Len: %d\n", SizeList(list));
InsertHeadList(list, 5); PrintList(list); // 5 10 20 30
InsertTailList(list, 40); PrintList(list); // 5 10 20 30 40
InsertNode(list, 2, 99); PrintList(list); // 5 10 99 20 30 40
DeletePosNode(list, 3); PrintList(list); // 5 10 20 30 40
DeleteValueNode(list, 5); PrintList(list); // 10 20 30 40
ClearList(list); PrintList(list); // (空)
return 0;
}
| 原則 | 體現 |
|---|---|
| 統一邊界 | 所有操作從 head 開始,無需判斷 head==NULL |
| 內存安全 | malloc 檢查、free 後置 NULL (此處省略為簡潔) |
| 位置語義 | 查找/刪除用 1-based;插入用 0-based (頭結點後) 更直觀 |
| 返回值 | 修改結構的操作返回 head,便於鏈式調用 |
這 13 個操作構成了單鏈表 ADT (抽象數據類型) 的完整語義集。帶頭結點設計消除了 80% 的特殊情況判斷,代碼行數減少、可讀性提升。建議將此作為個人「鏈表工具庫」模板,面試手寫、項目複用、教學演示皆宜。