在雙向循環鏈表中刪除節點,本質上是插入操作的逆過程。假設有三個連續節點 s、p、q,要刪除中間節點 p,只需將 s 的右鏈域指向 q,同時將 q 的左鏈域指向 s,最後釋放 p 佔用的內存即可完成刪除。這一操作保持了鏈表的雙向循環結構完整性。
下方展示一個基於雙向循環鏈表的學生信息管理系統,包含創建、查找、打印、刪除等核心功能:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
typedef struct node {
char name[20];
struct node *llink, *rlink;
} 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->llink = NULL;
h->rlink = NULL;
p = h;
for (i = 0; i < n; i++) {
if ((s = (stud *)malloc(sizeof(stud))) == NULL) {
printf("無法分配內存空間!\n");
exit(0);
}
p->rlink = s;
printf("請輸入第 %d 個人的姓名:", i + 1);
scanf("%s", s->name);
s->llink = p;
s->rlink = NULL;
p = s;
}
h->llink = s;
p->rlink = h;
return h;
}
/* 按姓名查找節點 */
stud *search(stud *h, char *x) {
stud *p;
char *y;
p = h->rlink;
while (p != h) {
y = p->name;
if (strcmp(y, x) == 0)
return p;
else
p = p->rlink;
}
printf("未查找到該數據!\n");
return NULL;
}
/* 打印鏈表所有節點 */
void print(stud *h) {
stud *p = h->rlink;
printf("數據信息為:\n");
while (p != h) {
printf("%s ", p->name);
p = p->rlink;
}
printf("\n");
}
/* 刪除指定節點 */
void del(stud *p) {
(p->rlink)->llink = p->llink;
(p->llink)->rlink = p->rlink;
free(p);
}
int main() {
int number = N;
char studname[20];
stud *head, *searchpoint;
head = creat(number);
print(head);
printf("請輸入你要查找的人的姓名:");
scanf("%s", studname);
searchpoint = search(head, studname);
if (searchpoint) {
printf("你所要查找的人的姓名是:%s\n", searchpoint->name);
del(searchpoint);
print(head);
}
return 0;
}
name[0]='\0' 標記為空,雙向指針初始化為 NULL。llink 指向尾節點,尾節點的 rlink 指向頭節點,形成循環。del() 函數通過修改前驅、後繼節點的指針域實現節點剔除,最後 free(p) 釋放內存,防止洩漏。rlink 開始遍歷,遇到頭節點則結束,未找到時返回 NULL 並提示。實際開發中需注意:刪除節點前務必確認節點存在(查找函數返回非 NULL);釋放內存後將指針置 NULL 避免野指針;輸入處理建議加入緩衝區溢出保護(如使用 fgets 替代 scanf)。雙向循環鏈表雖操作稍繁瑣,但支持雙向遍歷、O(1) 刪除已知節點,適合頻繁增刪場景。