在掌握顺序表和单链表之后,我们可以挑战结构更复杂的带头双向循环链表。虽然名字听起来复杂,但引入哨兵位头结点后,实际编码反而更加简洁,能减少大量边界判断。
结构概览
双向循环链表需要两个指针:一个指向后继节点,一个指向前驱节点。此外还需要一个不存储有效数据的头结点(哨兵位),这使得链表首尾相连,形成一个闭环。
这种结构的优势在于:
- 任意位置插入删除操作逻辑统一。
- 不需要特殊处理空表或首尾节点的情况。
- 支持从任意方向遍历。
核心定义与接口
首先定义节点结构和基本操作接口。注意 LTNode 中的 prev 和 next 指针构成了双向关系。
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int LDataType;
typedef struct ListNode {
LDataType val;
struct ListNode* next; // 指向后继节点
struct ListNode* prev; // 指向前驱节点
} LTNode;
// 初始化双向循环带头链表
LTNode* ListInit();
// 打印链表
void ListPrint(LTNode* phead);
// 尾插
void ListPushBack(LTNode* phead, LDataType x);
// 尾删
void ListPopBack(LTNode* phead);
// 头插
void ;
;
LTNode* ;
;
;
;


