首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言入門

C語言實現單鏈表節點刪除:按位置刪除與按值刪除雙算法詳解

     編輯:C 語言入門

單鏈表刪除操作分為按位置刪除與按值刪除兩大類。無頭結點版本需特判首節點刪除(更新頭指針),邏輯稍顯繁瑣。本文詳細實現兩種刪除算法,並對比其適用場景。

節點定義與輔助函數

typedef struct Node {
    int element;
    struct Node* next;
} Node;

int SizeList(Node* head);  // 獲取長度

算法一:按位置刪除

Node* DeletePosElement(Node* pHead, int pos) {
    // pos: 1-based,1=首節點,size=尾節點
    int size = SizeList(pHead);
    if (pos <= 0 || pos > size) {
        printf("%s: pos=%d 非法\n", __FUNCTION__, pos);
        return pHead;
    }
    
    Node* pMove = pHead;
    
    // 特判:刪除首節點
    if (pos == 1) {
        pHead = pHead->next;
        free(pMove);
        printf("%s: 刪除首節點成功\n", __FUNCTION__);
        return pHead;  // 新頭指針
    }
    
    // 定位到第 pos-1 個節點(被刪節點的前驅)
    for (int i = 1; i < pos - 1; i++) {
        pMove = pMove->next;
    }
    
    Node* pDel = pMove->next;
    pMove->next = pDel->next;
    free(pDel);
    printf("%s: 刪除 pos=%d 成功\n", __FUNCTION__, pos);
    return pHead;
}

算法二:按值刪除(刪除首個匹配值)

Node* DeleteXElement(Node* pHead, int x) {
    if (!pHead) {
        printf("%s: 鏈表為空\n", __FUNCTION__);
        return NULL;
    }
    
    Node *pPrev = pHead, *pCurr = pHead->next;
    
    // 特判:首節點匹配
    if (pHead->element == x) {
        pHead = pHead->next;
        free(pPrev);
        printf("%s: 刪除首節點值 x=%d 成功\n", __FUNCTION__, x);
        return pHead;
    }
    
    // 遍歷查找
    while (pCurr) {
        if (pCurr->element == x) {
            pPrev->next = pCurr->next;
            free(pCurr);
            printf("%s: 刪除值 x=%d 成功\n", __FUNCTION__, x);
            return pHead;
        }
        pPrev = pCurr;
        pCurr = pCurr->next;
    }
    
    printf("%s: 未找到值 x=%d\n", __FUNCTION__, x);
    return pHead;
}

關鍵差異對比

維度按位置刪除按值刪除
輸入參數索引 pos (1-based)目標值 x
查找方式直接計數定位遍歷比對 element
時間複雜度O(pos)O(n) 最壞
刪除語義精確位置首個匹配值
適用場景隨機訪問、索引操作業務邏輯按值刪除

指針操作圖解(刪除中間節點)

刪除前:  A -> B -> C -> D
         pPrev  pCurr

操作:    pPrev->next = pCurr->next;  // A->next = C
         free(pCurr);                 // 釋放 B

刪除後:  A -> C -> D

測試驗證

int main() {
    Node* list = CreateList();  // 尾插法建表:10 20 30 40 50
    PrintList(list);            // 10 20 30 40 50
    
    list = DeletePosElement(list, 1);  // 刪除首個 -> 20 30 40 50
    PrintList(list);
    
    list = DeletePosElement(list, 3);  // 刪除第3個 -> 20 30 50
    PrintList(list);
    
    list = DeleteXElement(list, 30);   // 刪除值30 -> 20 50
    PrintList(list);
    
    list = DeleteXElement(list, 99);   // 不存在
    PrintList(list);                   // 20 50
    
    return 0;
}

工程級建議:引入頭結點統一邏輯

無頭結點版本的「首節點特判」是 Bug 高發區。帶頭結點單鏈表下,刪除統一為:

// 統一刪除邏輯(帶頭結點)
Node* pPrev = pHead;  // 頭結點作為哨兵
while (pPrev->next) {
    if (/* 條件 */) {
        Node* pDel = pPrev->next;
        pPrev->next = pDel->next;
        free(pDel);
        break;
    }
    pPrev = pPrev->next;
}

無需特判首節點,頭指針永不變,代碼更簡潔健壯。實際項目強烈推薦帶頭結點版本。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved