第一部分:基础概念回顾
在学习跳舞链之前,必须先掌握双向链表和循环链表的概念。
1. 循环链表 (Circular Linked List)
- 定义:它是一种特殊的单链表,其最后一个结点的
next指针不再指向NULL,而是指向链表的第一个结点(或头结点/哨兵结点),形成一个环。 - 特点:从链表中的任意一个结点出发,都可以遍历到整个链表的所有结点。
- 判断空表:对于带头结点
head的循环链表,当head->next == head时,链表为空。 - 应用:约瑟夫问题 (Josephus Problem) 是其经典应用场景。
2. 双向链表 (Doubly Linked List)
- 定义:每个结点除了有数据域
data和指向后继结点的next(或right)指针外,还有一个指向前驱结点的prev(或left)指针。 - 特点:可以双向遍历,从一个结点可以很方便地找到它的前驱和后继,使得插入和删除操作更加灵活。
- 结构:通常有一个头指针
head指向第一个结点,尾结点的right指针为NULL;头结点的left指针也为NULL。
第二部分:核心知识点一:跳舞链 (Dancing Links)
“跳舞链”这个名字听起来很酷,但其本质并不复杂。PPT中提到的“跳舞链”实际上是 带哨兵结点的双向循环链表。
1. 结构定义
- 它是一个双向的、循环的链表。
- 它包含一个特殊的“哨兵”结点(通常称为
head或0号结点),这个结点不存储实际数据,只用于辅助操作,使代码更简洁。 - 表头:第一个有数据的元素是
head->right。 - 表尾:最后一个有数据的元素是
head->left。 - 空表示:当
head->right == head或head->left == head时,链表为空。
这种结构的最大优势在于 插入和删除操作极其高效且代码统一。因为链表是循环的,且有哨兵结点,所以不需要为“在表头/表尾插入/删除”或“在空表插入”等情况写额外的判断逻辑。所有位置的插入和删除操作都可以用同样的代码完成。
2. 核心操作:删除与插入
这是跳舞链的精髓,笔试和机试都极有可能考到。
删除结点 x:
想象一下 x 结点和它的左邻居 L、右邻居 R。要删除 x,就是让 L 和 R “手拉手”,直接跳过 x。
x的左邻居L的right指针,原本指向x,现在应该指向x的右邻居R。- 代码:
x->left->right = x->right;
- 代码:
x的右邻居R的left指针,原本指向x,现在应该指向x的左邻居L。- 代码:
x->right->left = x->left;
- 代码:
恢复(插入)结点 x:
删除是“跳过”,恢复就是让 L 和 R 松开手,重新和 x 连接。
x的左邻居L的right指针,重新指向x。- 代码:
x->left->right = x;
- 代码:
x的右邻居R的left指针,重新指向x。- 代码:
x->right->left = x;
- 代码:
这两个操作的时间复杂度都是 O(1)O(1)O(1),非常高效。
第三部分:核心知识点二:静态链表 (Static Linked List)
1. 为什么需要静态链表?
- 语言限制:在一些早期的编程语言(如 FORTRAN, BASIC)中,没有指针数据类型,无法使用
new或malloc动态分配内存。 - 性能考量:在现代C++等语言中,如果需要频繁地创建和销毁结点,
malloc/free或new/delete的系统调用开销可能较大。静态链表预先分配一大块连续内存,所有操作都在这块内存中进行,速度更快。
2. 实现原理
其核心思想是 用数组来模拟链表。我们不使用内存地址指针,而是使用数组下标(Index) 来“指向”下一个元素。
- 一个大数组(或几个平行数组)作为内存池。
- 每个结点包含两个关键部分:
data(数据域)和next(游标/指针域)。next存储的是下一个结点在数组中的下标。 - 通常用数组的
0号元素作为哨兵结点。
3. 两种实现方式
方式一:结构体数组 (Struct Array)
// C++
#include <iostream>
#define MAXN 1000
struct Node {
int data;
int next;
};
Node link[MAXN];
int tot = 0; // 当前已分配的结点计数器
// 初始化哨兵结点
void init() {
link[0].next = 0; // 0的next指向0,表示链表为空
}
// 头插法
void insert_head(int val) {
tot++;
link[tot].data = val;
link[tot].next = link[0].next;
link[0].next = tot;
}
// 遍历
void print_list() {
for

最低0.47元/天 解锁文章
32万+

被折叠的 条评论
为什么被折叠?



