数据结构中的单向链表

2025 年 4 月 21 日 | 阅读 17 分钟

链表乍一看可能有点复杂,但它们非常实用。本质上,你有一堆独立的节点,就像单独的积木。每个节点存储一块数据,比如一个数字或一些有用的信息。但不仅如此——它还有一个特殊的指针,指向序列中的下一个节点。

现在,与数组中所有元素都整齐地排列在内存中不同,这些节点可以散布在内存的各个位置。指针将它们连接成一个链。第一个节点称为头节点,最后一个节点指向 null,表示列表的末尾。

一个主要的优点是,你不需要预先决定列表需要多少内存。它可以通过在任何可用空间添加新节点来有机地增长。无需像数组那样移动所有内容或重新分配更大的内存块。

另一个优点是插入或删除项目非常快捷方便。你所做的只是更新一些指针来链接或取消链接节点。不需要大量的数据洗牌。这使得链表在你频繁添加或删除内容时非常方便。

当然,也有一些缺点。访问随机元素不像数组那样直接,因为你必须从头开始沿着链条查找。但对于主要处理开头或结尾的情况,链表非常棒。

  • 链表可以定义为称为**节点**的对象的集合,这些对象随机存储在内存中。
  • 一个节点包含两个字段,即存储在该特定地址的数据以及包含内存中下一个节点地址的指针。
  • 列表的最后一个节点包含指向 null 的指针。
  • 链表是一种以灵活和动态方式存储数据的方法
  • 节点通过引用/指针连接,而不是存储在内存中
  • 这使得列表可以根据需要轻松增长或缩小
  • 无需像数组那样预先分配固定量的内存
  • 插入和删除数据是高效的,就像更新指针一样
  • 链表通过不同的变体提供多功能性
  • 它可以构建双向链表、循环列表、树、图等。
  • 广泛用于算法、数据处理、内存管理
DS Linked List

链表在现实世界中的应用

由于其动态特性和在某些场景中的效率,链表在现实世界中具有广泛的应用。让我们探讨其中一些实际用途

  • 内存管理:操作系统和编程语言运行时通常利用链表进行动态内存分配和释放。当你请求内存时,一个新节点被添加到链表中;当你释放内存时,该节点被移除。
  • 浏览器历史和缓存:现代网络浏览器使用链表来跟踪访问过的 URL 并缓存最近访问的页面以加快加载速度。每个访问过的页面都作为新节点添加,缓存管理算法根据访问频率和最近性等因素决定保留或删除哪些节点。
  • 音乐播放列表:流媒体服务和媒体播放器将播放列表表示为链表。每首歌曲都是一个节点,节点的顺序定义了播放序列。使用链表添加、删除或重新排列歌曲是高效的。
  • 撤消/重做操作:类似于栈,链表可用于在文本编辑器和其他应用程序中实现撤消/重做功能。每个编辑操作都作为节点存储,允许用户沿任一方向遍历列表以撤消或重做更改。
  • 路由算法:链表用于计算机网络和交通系统的路由算法。每个节点表示一个网络节点或一个位置,节点之间的链接表示连接或路线。
  • 在线多人游戏:在实时多人游戏中,链表通常用于管理活跃玩家列表。当新玩家加入时,一个节点被添加到列表中;当玩家离开时,他们的节点被移除。
  • 区块链技术:区块链是比特币等加密货币的基础,它本质上是一个链表。每个区块(节点)包含交易数据,并与前一个区块链接,形成一个不可变的记录链。
  • 图像查看器应用程序:图像查看器应用程序可以使用链表来存储和导航图像集合。每个节点代表一个图像,用户可以向前或向后移动列表。
  • 多项式表示:在计算机代数系统中,多项式可以使用链表高效地表示,其中每个节点存储项的系数和指数。
  • 实现其他数据结构:链表可以作为更复杂数据结构(如栈、队列和哈希表)的构建块,这些数据结构广泛用于各种应用程序中。

这些只是突出链表在现实世界场景中多功能性的一些例子。它们的动态特性、高效的插入和删除操作以及根据需要增长或缩小的能力使它们成为许多领域中宝贵的工具。

为什么使用链表而不是数组?

我们一直在使用数组来组织单独存储在内存中的分组元素。但是数组,尽管它们很棒,也有其自身的局限性,这使我们在某些情况下重新考虑我们的选择。了解链表何时可以介入并挽救局面是很好的!

我们需要注意的数组局限性

  1. 固定大小:在使用数组之前,我们需要知道它需要多少空间。一旦派对开始,调整大小将是件麻烦事。
  2. 不灵活的内存布局:数组元素必须连续存储在内存中。插入新元素需要按顺序重新排列整个队伍,前一个接一个。
  3. 性质僵硬:数组被创建时的大小所束缚。扩展在运行时变成一个昂贵的重新分配操作。

链表的优点

  1. 动态大小:与数组不同,链表可以在运行时根据需要动态增长或缩小。这种灵活性允许高效的内存利用,尤其是在处理大型或可变大小数据集时。
  2. 高效的插入和删除:从链表中添加或删除元素相对简单和高效。它只需要更新周围节点的下一个指针,无需进行昂贵的操作,如移动或重新分配内存。
  3. 非连续内存分配:链表可以将其节点存储在非连续的内存位置,从而实现更好的内存管理和利用,尤其是在连续内存块稀缺的情况下。
  4. 多功能性:链表可以轻松地适应实现其他数据结构,如栈、队列,甚至树和图等高级结构。这种多功能性使它们成为各种算法和应用程序中的宝贵工具。
  5. 插入顺序保留:链表自然地保持插入顺序,这在某些需要元素顺序的应用程序中可能很有益。

链表的缺点

  1. 随机访问效率低下:访问链表中特定索引处的元素需要从头或尾遍历,使得随机访问操作与数组相比相对较慢。
  2. 额外内存开销:链表中的每个节点都需要额外的内存来存储指向下一个(以及可能的前一个)节点的指针,导致比数组更高的内存开销。
  3. 缺乏缓存局部性:链表节点在内存中分散,这可能导致较差的缓存局部性和性能问题,尤其是在需要频繁遍历的操作中。
  4. Null 终止要求:链表需要一个特殊的终止节点(通常为 null)来指示列表的结束,在某些操作中增加了一个额外的步骤。
  5. 反向遍历的复杂性:在单向链表中,反转或反向遍历列表并不简单,可能需要额外的操作或单独的实现。
  6. 数据丢失风险:如果节点的指针被无意中覆盖或损坏,可能导致链接断裂,并可能失去对链表一部分的访问,从而导致数据丢失。

虽然链表在动态大小、高效插入/删除和多功能性方面具有优势,但它们也伴随着随机访问性能、额外内存开销以及某些操作中潜在复杂性方面的权衡。选择使用链表还是数组最终取决于应用程序的具体要求,例如数据集的预期大小、插入和删除的频率以及随机访问性能的重要性。

单向链表或单向链

单向链表可以定义为有序元素集合。元素的数量可以根据程序的需要而变化。单向链表中的一个节点由两部分组成:数据部分和链接部分。节点的数据部分存储要由节点表示的实际信息,而节点的链接部分存储其直接后继的地址。

单向链或单向链表只能沿一个方向遍历。换句话说,我们可以说每个节点只包含下一个指针,因此我们不能反向遍历列表。

考虑一个例子,其中学生在三个科目中获得的分数存储在链表中,如图所示。

DS Singly Linked List

在上图中,箭头表示链接。每个节点的数据部分包含学生在不同科目中获得的分数。列表中的最后一个节点由最后一个节点地址部分中存在的空指针标识。我们可以根据需要,在列表的数据部分中拥有任意数量的元素。

复杂度

数据结构时间复杂度空间复杂度
 平均数最坏最坏
 访问搜索插入删除访问搜索插入删除 
单向链表θ(n)θ(n)θ(1)θ(1)O(n)O(n)O(1)O(1)O(n)

单向链表上的操作

可以在单向链表上执行各种操作。以下是所有此类操作的列表。

节点创建

插入

单向链表的插入可以在不同的位置执行。根据新节点插入的位置,插入分为以下几类。

序号操作描述
1在开头插入它涉及在列表前面插入任何元素。我们只需要进行一些链接调整,使新节点成为列表的头部。
2在列表末尾插入它涉及在链表的末尾插入。新节点可以作为列表中唯一的节点插入,也可以作为最后一个节点插入。每种情况下都实现了不同的逻辑。
3在指定节点后插入它涉及在链表的指定节点之后插入。我们需要跳过所需数量的节点才能到达将插入新节点的节点之后的位置。

删除和遍历

从单向链表中删除节点可以在不同的位置执行。根据要删除节点的位置,操作分为以下几类。

序号操作描述
1在开头删除它涉及从列表开头删除节点。这是所有操作中最简单的操作。它只需要对节点指针进行一些调整。
2在列表末尾删除它涉及删除列表的最后一个节点。列表可以为空或已满。针对不同的情况实现了不同的逻辑。
3在指定节点后删除它涉及删除列表中指定节点之后的节点。我们需要跳过所需数量的节点以到达将删除节点之后的节点。这需要遍历列表。
4遍历在遍历中,我们简单地至少访问列表中的每个节点一次,以便对其执行某些特定操作,例如打印列表中存在的每个节点的数据部分。
5搜索在搜索中,我们将列表中的每个元素与给定元素进行匹配。如果在任何位置找到该元素,则返回该元素的位置,否则返回 null。

C 语言中的链表:菜单驱动程序

示例

编译并运行

输出

			*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
1

Enter value
1

Node inserted

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
2

Enter value?
2

Node inserted

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
3

Enter element value1

Enter the location after which you want to insert 1

Node inserted

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
8

printing values . . . . .

1
2
1

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
2

Enter value?
123

Node inserted

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
1

Enter value
1234

Node inserted

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
4

Node deleted from the begining ...

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
5

Deleted Node from the last ...

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
6

Enter the location of the node after which you want to perform deletion 
1

Deleted node 2 

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
8

printing values . . . . .

1
1

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
7

Enter item which you want to search?
1
item found at location 1 
item found at location 2 

*********Main Menu*********

Choose one option from the following list ...

===============================================

1.Insert in begining
2.Insert at last
3.Insert at any random location
4.Delete from Beginning
5.Delete from last
6.Delete node after specified location
7.Search for an element
8.Show
9.Exit

Enter your choice?
9

Python 程序

示例

立即执行

输出

1. Push
2. Append
3. Insert After   
4. Delete Head    
5. Delete Tail    
6. Delete By Value
7. Traverse       
8. Search
0. Exit
Your move: 1      
Enter the data for the node to push: 12
Node inserted! Next?
1. Push
2. Append
3. Insert After     
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 1
Enter the data for the node to push: 34
Node inserted! Next?
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 2
Enter the data for the node to append: 45
Node Appeneded
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 3
Enter the node data to insert after: 12
Enter the data for the new node: 99
Node inserted
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 7
Data in the list:
34 12 99 45
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 4
Head removed!
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 5
Tail Node Is Updated
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 7
Data in the list:
12 99
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 6
Enter the node data to delete: 99
Node Deleted Succesfully. 
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 8 
Enter the data to search: 12
There it is! Your data is at node 0
1. Push
2. Append
3. Insert After
4. Delete Head
5. Delete Tail
6. Delete By Value
7. Traverse
8. Search
0. Exit
Your move: 0
PS C:\Users\HP>

下一个主题双向链表