在單鏈表中刪除已知位置的節點 p,核心步驟是:將 p 的前驅節點的 link 指針指向 p 的後繼節點,隨後釋放 p 佔用的內存。由於單鏈表只能單向遍歷,刪除操作通常需要先找到目標節點的直接前驅。
以下程序實現了帶頭節點的單鏈表創建、按姓名查找、查找前驅節點、刪除指定節點等功能:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define N 10
typedef struct node {
char name[20];
struct node *link;
} stud;
/* 創建單鏈表 */
stud *creat(int n) {
stud *p, *h, *s;
int i;
if ((h = (stud *)malloc(sizeof(stud))) == NULL) {
printf("無法分配內存空間!\n");
exit(0);
}
h->name[0] = '\0';
h->link = NULL;
p = h;
for (i = 0; i < n; i++) {
if ((s = (stud *)malloc(sizeof(stud))) == NULL) {
printf("無法分配內存空間!\n");
exit(0);
}
p->link = s;
printf("請輸入第 %d 個人的姓名:", i + 1);
scanf("%s", s->name);
s->link = NULL;
p = s;
}
return h;
}
/* 查找目標節點 */
stud *search(stud *h, char *x) {
stud *p = h->link;
char *y;
while (p != NULL) {
y = p->name;
if (strcmp(y, x) == 0)
return p;
else
p = p->link;
}
if (p == NULL)
printf("未查找到該數據!\n");
return NULL;
}
/* 查找目標節點的直接前驅 */
stud *search2(stud *h, char *x) {
stud *p = h->link, *s = h;
char *y;
while (p != NULL) {
y = p->name;
if (strcmp(y, x) == 0)
return s;
else {
p = p->link;
s = s->link;
}
}
if (p == NULL)
printf("未查找到該數據!\n");
return NULL;
}
/* 刪除節點:x為前驅,y為目標 */
void del(stud *x, stud *y) {
stud *s = y;
x->link = y->link;
free(s);
}
int main() {
int number = N;
char fullname[20];
stud *head, *searchpoint, *forepoint;
head = creat(number);
printf("請輸入你要刪除的人的姓名:");
scanf("%s", fullname);
searchpoint = search(head, fullname);
forepoint = search2(head, fullname);
if (searchpoint && forepoint)
del(forepoint, searchpoint);
return 0;
}
search() 返回目標節點指針,search2() 返回前驅節點指針,配合實現刪除。search2() 中雙指針 p、s 同步移動,s 始終滯後一步,指向 p 的前驅。s=y,斷鏈後 free(s) 釋放內存。實際項目中可考慮:將查找與刪除合併為單次遍歷,減少時間開銷;增加鏈表長度統計字段;使用雙向鏈表簡化刪除邏輯;引入哨兵節點簡化邊界判斷。單鏈表刪除雖需 O(n) 查找前驅,但結構簡單、內存開銷小,適用於插入刪除較少、以遍歷查詢為主的場景。