链表种类
单向链表(Singly Linked List)
为避免元素的移动,采用线性表的另一种存储方式:链式存储结构。链表是一种在物理上非连续、非顺序的数据结构,由若干结点(node)所组成。
单向链表的每一个结点又包含两部分,一部分是存放数据的数据域 data,另一部分是指向下一个结点的指针域 next。结点可以在运行时动态生成。
C
typedef struct node_t {
T data;
struct node_t *next;
} node_t;链表的第一个结点被称为头结点,最后一个结点被称为尾结点,尾结点的 next 指针指向 NULL。
知识测验
题目
单向链表尾结点的
next 通常保存什么?
与数组按照下标来随机寻找元素不同,对于链表的其中一个结点 A,只能根据结点 A 的 next 指针来找到该结点的下一个结点 B,再根据结点 B 的 next 指针找到下一个结点 C……
数组在内存中的存储方式是顺序存储,链表在内存中的存储方式则是随机存储。链表采用了见缝插针的方式,每一个结点分布在内存的不同位置,依靠 next 指针关联起来。这样可以灵活有效地利用零散的碎片空间。
双向链表(Doubly Linked List)
那么,通过链表的一个结点,如何能快速找到它的前一个结点呢?要想让每个结点都能回溯到它的前置结点,可以使用双向链表。
双向链表比单向链表稍微复杂一点,它的每一个结点除了拥有 data 和 next 指针,还拥有指向前置结点的 prev 指针。
C
typedef struct node_t {
T data;
struct node_t *prev;
struct node_t *next;
} node_t;知识测验
题目
把结点 X 插入双向链表的 A 与 B 之间,哪组连接必须最终成立?
单向链表只能从头到尾遍历,只能找到后继,无法找到前驱,因此遍历的时候不会死循环。而双向链表需要多分配一个指针的存储空间,每个结点有两个指针,分别指向直接前驱和直接后继。
循环链表(Circular Linked List)
除了单向链表和双向链表以外,还有循环链表。对于单向循环链表,尾结点的 next 指针指向头结点。对于双向循环链表,尾结点的 next 指针指向头结点,并且头结点的 prev 指针指向尾结点。
互动实验
探索链表的连接方式
访问权限PRO
PRO EXCLUSIVE探索不止于此
尊享 Pro 权益解锁完整互动实验、进阶解析与精选参考答案。
知识测验
题目
遍历非空循环链表时,哪种停止条件最合适?
动手练习
为场景选择链表
为每个场景选择单向链表、双向链表或循环链表,并说明理由:
- 编辑器的撤销/重做历史。
- 不断轮换执行任务的调度器。
- 只允许向前读取的日志流。
- 说明这三种链表按位置访问第 i 个结点的共同复杂度。