4、链表
4.1、使用场景
- 在许多列表,队列和堆栈实现中使用;
- 非常适合创建循环列表;
- 可以轻松地对诸如火车等现实世界的物体进行建模;
- 某些特定的Hashtable实现用于处理散列冲突;
- 用于图的邻接表的实现中。
4.2、术语
Head:链表中的第一个节点;
Tail:链表中的最后一个节点;
Pointer:指向下一个节点;
Node:一个对象,包含数据和Pointer。

4.3、实现思路
这里使用双向链表作为例子进行说明。
4.3.1、插入节点
往第三个节点插入:x
从链表头遍历,直到第三个节点,然后执行如下插入操作:
遍历到节点位置,把新节点指向前后继节点:

后继节点回溯连接到新节点,并移除旧的回溯关系:

前继节点遍历连接到新节点,并移除旧的遍历关系:

完成:

注意指针处理顺序,避免在添加过程中导致遍历出现异常。
4.3.2、删除节点
删除c节点:
从链表头遍历,直到找到c节点,然后把c节点的前继节点连接到c的后继接节点:

把c节点的后继节点连接到c的前继节点:

移除多余指向关系以及c节点:

完成:

同样的,注意指针处理顺序,避免在添加过程中导致遍历出现异常。
4.4、时间复杂度
| 操作 | 单向链表 | 双向链表 |
|---|---|---|
| 查找 | O(n) | O(n) |
| Insert at head | O(1) | O(1) |
| 中间追加 | O(n) | O(n) |
| 尾部追加 | O(1) | O(1) |
| 头部移除 | O(1) | O(1) |
| 尾部移除 | O(n) | O(1) |
| 中间移除 | O(n) | O(n) |
4.5、编程实践
-
JDK中的实现:
java.util.LinkedList -
练习: