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

C 語言帶頭尾節點雙向鏈表刪除操作:按位置與按值刪除完整實現

     編輯:關於C語言

從「無頭節點」到「帶頭尾節點」的質變

在《C語言實現非循環雙鏈表節點的刪除(不帶頭結點)》中,刪除頭節點、尾節點、中間節點分別需要不同邏輯,極易出錯。引入虛擬頭尾節點後,所有節點統一為「中間節點」,刪除邏輯簡化為兩行指針重連:

pMove->prior->next = pMove->next;
pMove->next->prior = pMove->prior;

核心刪除函數

1. 按位置刪除 DeletePosList

// 刪除第 pos 個節點 (1-based),成功返回 1
int DeletePosList(Node *pHead, Node *pTail, int pos) {
    if (pos < 1) return 0;                // 非法位置

    Node *pMove = pHead->next;            // 首個真實節點
    int i = 1;

    while (pMove != pTail) {              // 未越過尾哨兵
        if (i == pos) {
            pMove->prior->next = pMove->next;
            pMove->next->prior = pMove->prior;
            free(pMove);
            pMove = NULL;
            printf("%s: 刪除 pos=%d 成功\n", __FUNCTION__, pos);
            return 1;
        }
        i++;
        pMove = pMove->next;
    }
    printf("%s: 刪除 pos=%d 失敗(越界)\n", __FUNCTION__, pos);
    return 0;
}

2. 按值刪除 DeleteValueList

// 刪除第一個值為 x 的節點,成功返回 1
int DeleteValueList(Node *pHead, Node *pTail, int x) {
    Node *pMove = pHead->next;
    while (pMove != pTail) {
        if (pMove->element == x) {
            pMove->prior->next = pMove->next;
            pMove->next->prior = pMove->prior;
            free(pMove);
            pMove = NULL;
            printf("%s: 刪除值 x=%d 成功\n", __FUNCTION__, x);
            return 1;
        }
        pMove = pMove->next;
    }
    printf("%s: 刪除值 x=%d 失敗(不存在)\n", __FUNCTION__, x);
    return 0;
}

完整可運行示例

#include <stdio.h>
#include <stdlib.h>

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

// 初始化帶頭尾節點的空鏈表
void InitList(Node **ppHead, Node **ppTail) {
    *ppHead = (Node *)malloc(sizeof(Node));
    *ppTail = (Node *)malloc(sizeof(Node));
    (*ppHead)->next = *ppTail;
    (*ppTail)->prior = *ppHead;
    (*ppHead)->prior = (*ppTail)->next = NULL;
}

// 尾插建立測試數據 10 20 30 40 50
void BuildDemo(Node *pHead, Node *pTail) {
    for (int v = 10; v <= 50; v += 10) {
        Node *p = (Node *)malloc(sizeof(Node));
        p->element = v; p->prior = p->next = NULL;
        p->prior = pTail->prior;
        p->next = pTail;
        pTail->prior->next = p;
        pTail->prior = p;
    }
}

// 正向列印
void PrintList(Node *pHead, Node *pTail) {
    for (Node *p = pHead->next; p != pTail; p = p->next)
        printf("%d ", p->element);
    printf("\n");
}

int main() {
    Node *pHead, *pTail;
    InitList(&pHead, &pTail);
    BuildDemo(pHead, pTail);

    printf("初始: "); PrintList(pHead, pTail);   // 10 20 30 40 50

    DeletePosList(pHead, pTail, 3);              // 刪除第 3 個 (30)
    printf("刪除第3個: "); PrintList(pHead, pTail); // 10 20 40 50

    DeleteValueList(pHead, pTail, 10);           // 刪除值 10
    printf("刪除值10: "); PrintList(pHead, pTail);  // 20 40 50

    DeletePosList(pHead, pTail, 100);            // 越界測試
    DeleteValueList(pHead, pTail, 999);          // 不存在測試

    // 釋放所有節點(含頭尾)略
    return 0;
}

關鍵點總結

  1. 統一邏輯:頭尾哨兵消除特例判斷,刪除碼 僅 2 行。
  2. 內存安全:free 後立即置 NULL,防野指針。
  3. 錯誤處理:位置越界、值不存在均有明確返回碼與日誌。
  4. 擴展性:同框架輕鬆支持「刪除所有值為 x 的節點」「區間刪除」等高級操作。

完整項目代碼見 GitHub:DeleteNodeDoubleLinkedList_HeadList。

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