iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
Software Development

用leetcode系統化學習C語言系列 第 28

指標進階 — 操作鏈結串列的中階技巧

  • 分享至 

  • xImage
  •  

在學指標的時候,大家都會有那麼一瞬間覺得——
「為什麼這東西看起來像在自言自語?」
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;
}

}


上一篇
指標排序與邏輯思維訓練
下一篇
指標進階 2— 雙向鏈結串列
系列文
用leetcode系統化學習C語言30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言