链表 (Linked List)
LNode
Define (定义)
链表 是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。
Structure (类型)
单向链表:链表中最简单的一种是单向链表,它包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。

双向链表:与单向链表相比,双向链表记录了两个方向的引用。双向链表的节点定义同时包含指向后继节点(下一个节点)和前驱节点(上一个节点)的引用(指针)。相较于单向链表,双向链表更具灵活性,可以朝两个方向遍历链表,但相应地也需要占用更多的内存空间。

环形链表:如果我们令单向链表的尾节点指向头节点(首尾相接),则得到一个环形链表。在环形链表中,任意节点都可以视作头节点。

用单向链表构建的循环链表
Application (应用)
单向链表通常用于实现栈、队列、哈希表和图等数据结构。
栈与队列:当插入和删除操作都在链表的一端进行时,它表现出先进后出的特性,对应栈;当插入操作在链表的一端进行,删除操作在链表的另一端进行,它表现出先进先出的特性,对应队列。
哈希表:链式地址是解决哈希冲突的主流方案之一,在该方案中,所有冲突的元素都会被放到一个链表中。
图:邻接表是表示图的一种常用方式,其中图的每个顶点都与一个链表相关联,链表中的每个元素都代表与该顶点相连的其他顶点。
双向链表常用于需要快速查找前一个和后一个元素的场景。
高级数据结构:比如在红黑树、B 树中,我们需要访问节点的父节点,这可以通过在节点中保存一个指向父节点的引用来实现,类似于双向链表。
浏览器历史:在网页浏览器中,当用户点击前进或后退按钮时,浏览器需要知道用户访问过的前一个和后一个网页。双向链表的特性使得这种操作变得简单。
LRU 算法:在缓存淘汰(LRU)算法中,我们需要快速找到最近最少使用的数据,以及支持快速添加和删除节点。这时候使用双向链表就非常合适。
环形链表常用于需要周期性操作的场景,比如操作系统的资源调度。
时间片轮转调度算法:在操作系统中,时间片轮转调度算法是一种常见的 CPU 调度算法,它需要对一组进程进行循环。每个进程被赋予一个时间片,当时间片用完时,CPU 将切换到下一个进程。这种循环操作可以通过环形链表来实现。
数据缓冲区:在某些数据缓冲区的实现中,也可能会使用环形链表。比如在音频、视频播放器中,数据流可能会被分成多个缓冲块并放入一个环形链表,以便实现无缝播放。
Code Example (代码实例)
Singly linked list (单链表)
结构
初始化
头插入
尾插入
删除
搜索
完整代码
Double linked list (双向链表)
在单链表的基础上,双链表(Double linked list)是其扩展形式。区别在于双链表的节点不仅仅含有指向下一个节点的指针,同时还含有指向上一个节点的指针。这使得双链表可以从两个方向遍历:向前和向后。
结构定义
创建新节点
创建新节点时,需要初始化其数据部分,以及前后指针部分。
添加节点
在双链表中添加节点稍微复杂一些,因为除了要处理新节点的next指针,还要处理prev指针。
遍历
双链表既可以向前遍历也可以向后遍历,提供更多的灵活性。
通过以上定义和函数,我们可以灵活地管理和使用双链表数据结构,轻松地进行节点的添加、删除和遍历操作。
Circular linked list (循环链表)
循环链表是链表的一种,其中最后一个节点指向链表的第一个节点,形成一个环。与单链表和双链表相比,循环链表的优点是从链表的任何一个节点都可以访问到链表中的所有其他节点。这种类型的链表在需要周期性访问各个节点的场合(如轮转调度算法)中特别有用。
循环链表的实现可以基于单链表或双链表的结构进行扩展,主要的区别在于链表的尾节点指向链表的头节点,形成一个闭环。
完整代码:
Citing (引用)
Last updated
Was this helpful?