在學指標的時候,大家都會有那麼一瞬間覺得——
「為什麼這東西看起來像在自言自語?」
Node *next = head->next;
head = head->next;
head->next = newNode;
這些指向來指向去的程式,光看就讓人頭暈🤯
但其實,只要掌握了「指標思維」,鏈結串列會變成超好玩的資料結構。
今天,我們就來看三個實戰級技巧,正式從「會寫鏈結串列」→「能掌控鏈結串列」。
🌱 一、在任意位置插入節點
我們不只想在「頭」或「尾」新增節點,有時要在中間插入資料。這時候,就得靈活操作指標!
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
// 建立新節點
Node* createNode(int data) {
Node* newNode = malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// 在指定位置插入節點(位置從 0 開始)
void insertAt(Node** head, int pos, int data) {
Node* newNode = createNode(data);
if (pos == 0) {
newNode->next = *head;
*head = newNode;
return;
}
Node* temp = *head;
for (int i = 0; temp != NULL && i < pos - 1; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("位置超出範圍!\n");
free(newNode);
return;
}
newNode->next = temp->next;
temp->next = newNode;
}
// 印出鏈結串列
void printList(Node* head) {
for (Node* curr = head; curr != NULL; curr = curr->next)
printf("%d -> ", curr->data);
printf("NULL\n");
}
int main() {
Node* head = NULL;
insertAt(&head, 0, 10);
insertAt(&head, 1, 20);
insertAt(&head, 1, 15);
insertAt(&head, 3, 25);
printList(head);
return 0;
}
💡 關鍵思維:
使用 Node** head 才能直接修改原始鏈結串列的起點
插入中間時要「先記住原本的 next」,否則鏈會斷開。
🔄 二、反轉鏈結串列(Iterative)
這題在面試超常出現,也是一個檢測「指標邏輯」是否通透的經典題。
Node* reverseList(Node* head) {
Node* prev = NULL;
Node* curr = head;
Node* next = NULL;
while (curr != NULL) {
next = curr->next; // 暫存下一個
curr->next = prev; // 反轉指向
prev = curr; // 前進
curr = next;
}
return prev; // 新的頭節點
}
觀念補充:
三個指標 (prev, curr, next) 就像三人接力賽,只要少交一次棒,鏈結整條報銷
順序很重要:先記住 next → 再反轉 → 再前進。
⚔️ 三、刪除指定值的節點
刪除節點時最常出錯的地方,就是沒更新 head 或忘了處理「連續多個相同值」。
我們用以下方式安全刪除:
void deleteValue(Node** head, int value) {
Node* temp = head;
Node prev = NULL;
// 刪除開頭重複值
while (temp != NULL && temp->data == value) {
*head = temp->next;
free(temp);
temp = *head;
}
// 刪除中間節點
while (temp != NULL) {
while (temp != NULL && temp->data != value) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
}