單鏈表以離散的記憶體節點儲存線性表,每個節點包含數據域與指針域,透過指針串聯邏輯順序。優勢在於插入/刪除無需移動元素,只需修改指針;缺點是無法隨機存取,查找為 O(n)。
typedef char DataType; // 假設數據為字符
typedef struct Node {
DataType data; // 數據域
struct Node *next; // 指針域,指向後繼節點
} ListNode;
typedef ListNode *LinkList; // 鏈表頭指針類型
LinkList head; // 頭指針變量
ListNode *p; // 普通節點指針
關鍵約定: 終端節點的 next = NULL;鏈表由頭指針唯一確定。
data 通常不存有效數據,便於統一插入/刪除邏輯(無需特判頭節點)。// 生成節點
ListNode *p = (ListNode *)malloc(sizeof(ListNode));
p->data = 'A';
p->next = NULL;
// 訪問成員:兩種等價寫法
(*p).data; // 解引用後取成員
p->data; // 箭頭運算符,更常用
// 釋放節點
free(p);
p = NULL; // 防野指標
| 指針變量 | 節點變量 | |
|---|---|---|
| 定義 | 編譯期顯式聲明 | 運行期 malloc 生成 |
| 值 | 節點地址 | 節點內容(數據+指針) |
| 操作 | 直接用變量名 | 透過指針間接訪問 |
LinkList create_list_tail(DataType a[], int n) {
LinkList head = (LinkList)malloc(sizeof(ListNode));
head->next = NULL;
ListNode *tail = head;
for (int i = 0; i < n; i++) {
ListNode *newnode = (ListNode *)malloc(sizeof(ListNode));
newnode->data = a[i];
newnode->next = NULL;
tail->next = newnode;
tail = newnode;
}
return head;
}
bool insert_node(LinkList head, int pos, DataType val) {
ListNode *pre = head;
int i = 0;
while (pre && i < pos - 1) { pre = pre->next; i++; }
if (!pre) return false;
ListNode *newnode = (ListNode *)malloc(sizeof(ListNode));
newnode->data = val;
newnode->next = pre->next;
pre->next = newnode;
return true;
}
bool delete_node(LinkList head, int pos) {
ListNode *pre = head;
int i = 0;
while (pre->next && i < pos - 1) { pre = pre->next; i++; }
if (!pre->next) return false;
ListNode *del = pre->next;
pre->next = del->next;
free(del);
return true;
}
p->next 前必須確認 p != NULL。free。free 後立即置 NULL。單鏈表是動態數據結構的基石,掌握「指針操作節點、節點串聯邏輯」的核心模式,便能舉一反三實現棧、佇列、圖的鄰接表等複雜結構。