雙向循環鏈表結合了「雙向指標」與「首尾相連」特性,使節點操作更靈活。本文詳細解析插入與刪除操作的指標調整邏輯,提供可直接運行的C++完整代碼。
typedef struct dnode {
int data;
struct dnode *preNode; // 前驅指標
struct dnode *nextNode; // 後繼指標
} dCycleLink;
在 p 節點後插入新節點 s:
s->preNode = p; // 新節點前驅指向 pp->nextNode->preNode = s; // p原後繼的前驅指向 ss->nextNode = p->nextNode; // 新節點後繼指向 p原後繼p->nextNode = s; // p的後繼指向新節點dCycleLink* insertData(dCycleLink *head, int pos, int data) {
assert(head != NULL);
dCycleLink *p = head;
int count = 1;
// 1. 定位到第 pos 個節點
while (p != NULL && count < pos) {
count++;
p = p->nextNode;
}
if (count == pos && p != NULL) {
// 2. 創建新節點
dCycleLink *s = (dCycleLink*)malloc(sizeof(dCycleLink));
if (s != NULL) {
s->data = data;
// 3. 四步指標重連(核心)
s->preNode = p; // 步驟1
p->nextNode->preNode = s; // 步驟2
s->nextNode = p->nextNode; // 步驟3
p->nextNode = s; // 步驟4
printf("插入成功!!!\n");
}
} else {
printf("插入失敗:位置越界!!!\n");
}
return head;
}
刪除節點 p:
p->preNode->nextNode = p->nextNode; // 前驅跳過 p 指向後繼p->nextNode->preNode = p->preNode; // 後繼跳過 p 指向前驅free(p); p = NULL; // 釋放記憶體dCycleLink* deleteData(dCycleLink* head, int data) {
assert(head != NULL);
dCycleLink* p = head;
// 1. 查找目標節點
while (p != NULL && p->data != data) {
p = p->nextNode;
}
if (p->data == data) { // 找到目標
// 2. 雙向斷鏈(核心)
p->preNode->nextNode = p->nextNode;
p->nextNode->preNode = p->preNode;
free(p);
p = NULL;
printf("找到目標,刪除成功!\n");
} else {
printf("未找到目標值,刪除失敗!\n");
}
return head;
}
dCycleLink* createDoublyCycleLink(int n) {
int xValue;
dCycleLink *head, *p, *pre;
printf("請輸入第1個數字:");
scanf("%d", &xValue);
p = (dCycleLink*)malloc(sizeof(dCycleLink));
p->data = xValue;
p->preNode = NULL;
p->nextNode = NULL;
head = p;
pre = p;
for (int i = 1; i < n; i++) {
printf("請輸入第%d個數字:", i+1);
scanf("%d", &xValue);
p = (dCycleLink*)malloc(sizeof(dCycleLink));
p->data = xValue;
p->nextNode = NULL;
p->preNode = pre; // 體現雙向特性
pre->nextNode = p;
pre = p;
}
// 注意:此處未閉環,若需循環需補上 head->preNode = pre; pre->nextNode = head;
return head;
}
void printCycleLink(dCycleLink *head) {
dCycleLink* pNode = head;
printf("鏈表數據:\n");
while (pNode) {
printf("%d ", pNode->data);
pNode = pNode->nextNode;
}
printf("\n");
}
int main() {
int num;
printf("請輸入節點個數:");
scanf("%d", &num);
dCycleLink* list = createDoublyCycleLink(num);
printCycleLink(list);
list = insertData(list, 2, 10); // 第2個位置插入10
list = deleteData(list, 2); // 刪除值為2的節點
return 0;
}
| 操作 | 核心步驟 | 易錯點 |
|---|---|---|
| 插入 | 四步指標重連,順序不可亂 | 忘記處理 p->nextNode->preNode |
| 刪除 | 雙向斷鏈後立即 free | 未置空指標導致野指標 |
| 循環特性 | 頭尾相連 | 創建時需手動閉環 |
雙向循環鏈表的優勢在於:既可正向遍歷也可逆向遍歷,插入刪除只需調整相鄰指標,無需從頭查找前驅節點。掌握指標調整的「四步法」(插入)與「雙向斷鏈」(刪除)是攻克此類問題的關鍵。