首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言單向鏈表插入節點:insect 函數錯誤分析與正確 insert 實現

     編輯:程式設計綜合問答

原代碼核心錯誤

int insect(Linklist L, char e, int k) {  // 1. 函數名拼寫錯誤:應為 insert
    Node *r; Linklist pre; int i = 0;
    pre = (Linklist)malloc(sizeof(Node));  // 2. 額外 malloc 產生記憶體洩漏,pre 應直接指向 L
    pre->data = L->data;                   // 3. 複製頭節點資料無意義
    while ((pre->next != NULL) && (i < k-1)) {
        pre = pre->next; k++;              // 4. k++ 錯誤:應為 i++,k 是目標位置不應修改
    }
    if (k != i-1) return 0;                // 5. 判斷邏輯錯誤:應檢查 i != k-1
    // ... 插入邏輯 ...
}

錯誤總結表

行號錯誤類型說明
函數名拼寫`insect` → `insert` (昆蟲 vs 插入)
pre 初始化記憶體/邏輯多餘 `malloc` 導致洩漏;應 `pre = L` 直接從頭節點開始尋找
迴圈計數變數誤用`k++` 應為 `i++`;`k` 是輸入參數(目標位置),不可修改
邊界判斷邏輯錯誤`if (k != i-1)` 應為 `if (i != k-1)` 或 `if (pre == NULL)`
頭節點處理設計缺陷若 `k=1` 插在第一個資料節點前,需特殊處理或統一用虛擬頭節點

正確 insert 實現(帶虛擬頭節點)

// 定義:Linklist 為 Node* ,頭節點不存資料,first = L->next
int insert(Linklist L, char e, int k) {  // k: 1-based 位置(1 表示第一個資料節點前)
    if (k < 1) return 0;  // 位置無效

    Linklist pre = L;     // 從頭節點開始
    int i = 0;
    // 尋找第 k-1 個節點(即插入位置的前驅)
    while (pre != NULL && i < k - 1) {
        pre = pre->next;
        i++;
    }
    if (pre == NULL) return 0;  // 位置超出鏈表長度+1

    // 建立新節點
    Node *r = (Node*)malloc(sizeof(Node));
    if (!r) return 0;  // 記憶體配置失敗
    r->data = e;
    r->next = pre->next;
    pre->next = r;
    return 1;
}

完整可測試主程式

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

typedef struct Node {
    char data;
    struct Node *next;
} Node, *Linklist;

// 建立鏈表:頭插法,以 $ 結束
Linklist CreateFromHead() {
    Linklist L = (Linklist)malloc(sizeof(Node));
    L->next = NULL;
    char c;
    while ((c = getchar()) != '$' && c != '\n' && c != EOF) {
        Node *s = (Node*)malloc(sizeof(Node));
        s->data = c;
        s->next = L->next;
        L->next = s;
    }
    return L;
}

// 印表
void PrintList(Linklist L) {
    Linklist p = L->next;
    while (p) {
        printf("%c ", p->data);
        p = p->next;
    }
    printf("\n");
}

// 釋放鏈表
void FreeList(Linklist L) {
    Linklist p = L, q;
    while (p) { q = p->next; free(p); p = q; }
}

int main() {
    printf("輸入字元序列以 $ 結束:");
    Linklist L = CreateFromHead();
    printf("建立後:"); PrintList(L);

    int k; char e;
    printf("輸入插入位置 k (1-based) 與字元 e:");
    scanf("%d %c", &k, &e);

    if (insert(L, e, k)) {
        printf("插入後:"); PrintList(L);
    } else {
        printf("插入失敗:位置無效或記憶體不足\n");
    }

    FreeList(L);
    return 0;
}

測試案例

輸入序列ke預期結果
a b c $1XX a b c
a b c $2Xa X b c
a b c $4Xa b c X
a b c $5X失敗(超出長度+1)

總結

單向鏈表插入核心三步:定位前驅 → 建立新節點 → 修改指標。關鍵細節:使用虛擬頭節點統一邊界處理、迴圈計數器不可汙染輸入參數、檢查 `malloc` 回傳值、釋放記憶體避免洩漏。將 `insect` 改為 `insert` 並修正上述邏輯即可正確運作。

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