原代碼核心錯誤
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;
}
測試案例
| 輸入序列 | k | e | 預期結果 |
| a b c $ | 1 | X | X a b c |
| a b c $ | 2 | X | a X b c |
| a b c $ | 4 | X | a b c X |
| a b c $ | 5 | X | 失敗(超出長度+1) |
總結
單向鏈表插入核心三步:定位前驅 → 建立新節點 → 修改指標。關鍵細節:使用虛擬頭節點統一邊界處理、迴圈計數器不可汙染輸入參數、檢查 `malloc` 回傳值、釋放記憶體避免洩漏。將 `insect` 改為 `insert` 並修正上述邏輯即可正確運作。