数据结构之线性表——循环链表
为了让链表的首尾操作更加便捷,循环链表对单链表或双链表的结构进行了改进,核心是让表尾结点的指针不再指向NULL,而是指向表头(头结点或首元结点),从而形成“环形”的链式结构。这种结构下,从链表中任意一个结点出发,都能遍历整个链表,也能更高效地实现“表尾与表头”的关联操作。下面分别介绍循环单链表和循环双链表。
1. 循环单链表
循环单链表是对单链表的扩展,它让表尾结点的next
指针指向头结点(或首元结点),使链表形成一个闭合的环。如图2.12“循环单链表”所示,头指针L
指向头结点,头结点的next
指向第一个存储元素的结点a₁
;后续结点a₁
的next
指向a₂
,依此类推;最后一个结点aₙ
的next
不再是NULL,而是指向头结点。
这种结构带来了几个关键特性:
- 遍历的连续性:从任意结点出发,通过
next
指针可以循环遍历整个链表(因为表尾结点的next
会带我们回到头部),无需担心“遇到NULL就停止”的情况; - 空表的判断:若循环单链表带头结点,空表的判断条件是“头结点的
next
是否指向自身”(即L->next == L
);若不带头结点,空表则是“头指针L
为NULL”; - 首尾操作的高效性:要找到表尾结点,无需从表头逐个遍历到NULL,只需判断结点的
next
是否为头结点即可,这让“在表尾插入结点”“合并两个循环单链表”等操作更高效(比如表尾插入时,能快速定位表尾,无需遍历)。
2. 循环双链表
循环双链表是对双链表的扩展,它同时让表尾结点的next
指针指向头结点,且头结点的prior
指针指向表尾结点,从而形成“双向循环”的结构。如图2.13“循环双链表”所示,头结点的next
指向首元结点a₁
,而a₁
的prior
指向头结点;后续结点a₁
的next
指向a₂
,a₂
的prior
指向a₁
;……;最后一个结点aₙ
的next
指向头结点,同时头结点的prior
指向aₙ
。
循环双链表的核心特性包括:
- 双向遍历的连续性:既可以通过
next
指针从前往后循环遍历,也可以通过prior
指针从后往前循环遍历,整个链表形成一个“无起点、无终点”的环; - 空表的判断:若带头结点,空表的判断条件是“头结点的
next
和prior
都指向自身”(即L->next == L
且L->prior == L
); - 首尾操作的便捷性:要获取表尾结点,无需从表头遍历,可直接通过头结点的
prior
得到;同理,表头结点也可通过表尾结点的next
得到,这让双向的首尾操作(如插入、删除)效率大幅提升。
简言之,循环链表通过“表尾连表头”的环形结构,增强了链表首尾操作的高效性,同时让遍历过程更具连续性,是单链表、双链表在特定场景下的优化形式。