Skip to content

Commit

Permalink
Update 01.Linked-List-Basic.md
Browse files Browse the repository at this point in the history
  • Loading branch information
itcharge committed Aug 29, 2022
1 parent b36df61 commit 4161866
Showing 1 changed file with 41 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

> **链表(Linked List)**:一种线性表数据结构。它使用一组任意的存储单元(可以是连续的,也可以是不连续的),来存储一组具有相同类型的数据。
简单来说,**「链表」** 是实现线性表的链式存储结构的基础
简单来说,**「链表」** 是实现线性表链式存储结构的基础

以单链表为例,链表的存储方式如下图所示。

Expand All @@ -16,9 +16,9 @@

我们先来简单介绍一下链表结构的优缺点:

- 优点:存储空间不必事先分配,在需要存储空间的时候可以临时申请,不会造成空间的浪费;一些操作的时间效率远比数组高(插入、移动、删除元素等)。
- **优点**:存储空间不必事先分配,在需要存储空间的时候可以临时申请,不会造成空间的浪费;一些操作的时间效率远比数组高(插入、移动、删除元素等)。

- 缺点:不仅数据元素本身的数据信息要占用存储空间,指针也需要占用存储空间,链表结构比数组结构的空间开销大。
- **缺点**:不仅数据元素本身的数据信息要占用存储空间,指针也需要占用存储空间,链表结构比数组结构的空间开销大。

接下来先来介绍一下除了单链表之外,链表的其他几种类型。

Expand All @@ -32,7 +32,7 @@

### 1.3 循环链表

> 循环链表(Circular linked list):链表的一种。它的最后一个链节点指向头节点,形成一个环。
> **循环链表(Circular linked list)**:链表的一种。它的最后一个链节点指向头节点,形成一个环。
从循环链表的任何一个节点出发都能找到任何其他节点。

Expand All @@ -42,7 +42,7 @@

## 2. 链表的基本操作

数据结构的操作一般涉及到增、删、改、查 4 种情况,链表的操作也基本上是这 4 种情况。下面我们一起来看一下链表的基本操作
数据结构的操作一般涉及到增、删、改、查 4 种情况,链表的操作也基本上是这 4 种情况。我们一起来看一下链表的基本操作

### 2.1 链表的结构定义

Expand Down Expand Up @@ -71,11 +71,11 @@ class LinkedList:

建立一个线性链表的过程是:根据线性表的数据元素动态生成链节点,并依次将其连接到链表中。其做法如下:

- 从所给线性表的第 `1` 个数据元素开始依次获取表中的数据元素。
- 每获取一个数据元素,就为该数据元素生成一个新节点,将新节点插入到链表的尾部。
- 插入完毕之后返回第 `1` 个链节点的地址。
1. 从所给线性表的第 `1` 个数据元素开始依次获取表中的数据元素。
2. 每获取一个数据元素,就为该数据元素生成一个新节点,将新节点插入到链表的尾部。
3. 插入完毕之后返回第 `1` 个链节点的地址。

建立一个线性链表的时间复杂度为 $O(n)$,`n` 为线性表长度。
建立一个线性链表的时间复杂度为 $O(n)$,$n$ 为线性表长度。

**「建立一个线性链表」** 的代码如下:

Expand All @@ -94,11 +94,11 @@ def create(self, data):

线性链表的长度被定义为链表中包含的链节点的个数。求线性链表的长度操作只需要使用一个可以顺着链表指针移动的指针变量 `cur` 和一个计数器 `count`。具体做法如下:

- 让指针变量 `cur` 指向链表的第 `1` 个链节点。
- 然后顺着链节点的 `next` 指针遍历链表,指针变量 `cur` 每指向一个链节点,计数器就做一次计数。
-` cur` 指向为空时结束遍历,此时计数器的数值就是链表的长度,将其返回即可。
1. 让指针变量 `cur` 指向链表的第 `1` 个链节点。
2. 然后顺着链节点的 `next` 指针遍历链表,指针变量 `cur` 每指向一个链节点,计数器就做一次计数。
3.` cur` 指向为空时结束遍历,此时计数器的数值就是链表的长度,将其返回即可。

求线性链表的长度操作的问题规模是链表的链节点数 `n`,基本操作是 `cur` 指针的移动,操作的次数为 `n`,因此算法的时间复杂度为 $O(n)$。
求线性链表的长度操作的问题规模是链表的链节点数 $n$,基本操作是 `cur` 指针的移动,操作的次数为 $n$,因此算法的时间复杂度为 $O(n)$。

**「求线性链表长度」** 的代码如下:

Expand All @@ -117,7 +117,7 @@ def length(self):

在链表中查找值为 `val` 的位置:链表不能像数组那样进行随机访问,只能从头节点 `head` 开始,沿着链表一个一个节点逐一进行查找。如果查找成功,返回被查找节点的地址。否则返回 `None`

查找元素操作的问题规模是链表的长度 `n`,而基本操作是指针 `cur` 的移动操作,所以查找元素算法的时间复杂度为 $O(n)$。
查找元素操作的问题规模是链表的长度 $n$,而基本操作是指针 `cur` 的移动操作,所以查找元素算法的时间复杂度为 $O(n)$。

**「在链表中查找元素」** 的代码如下:

Expand All @@ -137,19 +137,19 @@ def find(self, val):

链表中插入元素操作分为三种:

- 链表头部插入元素:在链表第 `1` 个链节点之前插入值为 `val` 的链节点。
- 链表尾部插入元素:在链表最后 `1` 个链节点之后插入值为 `val` 的链节点。
- 链表中间插入元素:在链表第 `i` 个链节点之前插入值为 `val` 的链节点。
- **链表头部插入元素**:在链表第 `1` 个链节点之前插入值为 `val` 的链节点。
- **链表尾部插入元素**:在链表最后 `1` 个链节点之后插入值为 `val` 的链节点。
- **链表中间插入元素**:在链表第 `i` 个链节点之前插入值为 `val` 的链节点。

接下来我们分别讲解一下。

#### 2.5.1 链表头部插入元素

算法实现的步骤为:

- 先创建一个值为 `val` 的链节点 `node`
- 然后将 `node``next` 指针指向链表的头节点 `head`
- 再将链表的头节点 `head ` 指向 `node`
1. 先创建一个值为 `val` 的链节点 `node`
2. 然后将 `node``next` 指针指向链表的头节点 `head`
3. 再将链表的头节点 `head ` 指向 `node`

![](https://qcdn.itcharge.cn/images/20211208180101.png)

Expand All @@ -169,14 +169,14 @@ def insertFront(self, val):

算法实现的步骤为:

- 先创建一个值为 `val` 的链节点 `node`
- 使用指针 `cur` 指向链表的头节点 `head`
- 通过链节点的 `next` 指针移动 `cur` 指针,从而遍历链表,直到 `cur.next == None`
-`cur.next` 指向将新的链节点 `node`
1. 先创建一个值为 `val` 的链节点 `node`
2. 使用指针 `cur` 指向链表的头节点 `head`
3. 通过链节点的 `next` 指针移动 `cur` 指针,从而遍历链表,直到 `cur.next == None`
4.`cur.next` 指向将新的链节点 `node`

![](https://qcdn.itcharge.cn/images/20211208180111.png)

因为将 `cur` 从链表头部移动到尾部的操作次数是 `n` 次,所以该算法的时间复杂度是 $O(n)$。
因为将 `cur` 从链表头部移动到尾部的操作次数是 $n$ 次,所以该算法的时间复杂度是 $O(n)$。

**「在链表尾部插入值为 `val` 的元素」** 的代码如下:

Expand All @@ -194,12 +194,12 @@ def insertRear(self, val):

算法的实现步骤如下:

- 使用指针变量 `cur` 和一个计数器 `count`。令 `cur` 指向链表的头节点,`count` 初始值赋值为 `0`
- 沿着链节点的 `next` 指针遍历链表,指针变量 `cur` 每指向一个链节点,计数器就做一次计数。
-`count == index - 1` 时,说明遍历到了第 `index - 1` 个链节点,此时停止遍历。
- 创建一个值为 `val` 的链节点 `node`
-`node.next` 指向 `cur.next`
- 然后令 `cur.next` 指向 `node`
1. 使用指针变量 `cur` 和一个计数器 `count`。令 `cur` 指向链表的头节点,`count` 初始值赋值为 `0`
2. 沿着链节点的 `next` 指针遍历链表,指针变量 `cur` 每指向一个链节点,计数器就做一次计数。
3.`count == index - 1` 时,说明遍历到了第 `index - 1` 个链节点,此时停止遍历。
4. 创建一个值为 `val` 的链节点 `node`
5.`node.next` 指向 `cur.next`
6. 然后令 `cur.next` 指向 `node`

![](https://qcdn.itcharge.cn/images/20211208180121.png)

Expand Down Expand Up @@ -228,10 +228,10 @@ def insertInside(self, index, val):

将链表中第 `i` 个元素值改为 `val`:首先要先遍历到第 `i` 个链节点,然后直接更改第 `i` 个链节点的元素值。具体做法如下:

- 使用指针变量 `cur` 和一个计数器 `count`。令 `cur` 指向链表的头节点,`count` 初始值赋值为 `0`
- 沿着链节点的 `next` 指针遍历链表,指针变量 `cur` 每指向一个链节点,计数器就做一次计数。
-`count == index` 时,说明遍历到了第 `index` 个链节点,此时停止遍历。
- 直接更改 `cur` 的值 `val`
1. 使用指针变量 `cur` 和一个计数器 `count`。令 `cur` 指向链表的头节点,`count` 初始值赋值为 `0`
2. 沿着链节点的 `next` 指针遍历链表,指针变量 `cur` 每指向一个链节点,计数器就做一次计数。
3.`count == index` 时,说明遍历到了第 `index` 个链节点,此时停止遍历。
4. 直接更改 `cur` 的值 `val`

因为将 `cur` 从链表头部移动到第 `i` 个链节点的操作平均时间复杂度是 $O(n)$,所以该算法的时间复杂度是 $O(n)$。

Expand All @@ -256,9 +256,9 @@ def change(self, index, val):

链表的删除元素操作同样分为三种情况:

- 链表头部删除元素:删除链表的第 `1` 个链节点。
- 链表尾部删除元素:删除链表末尾最后 `1` 个链节点。
- 链表中间删除元素:删除链表第 `i` 个链节点。
- **链表头部删除元素**:删除链表的第 `1` 个链节点。
- **链表尾部删除元素**:删除链表末尾最后 `1` 个链节点。
- **链表中间删除元素**:删除链表第 `i` 个链节点。

接下来我们分别讲解一下。

Expand Down Expand Up @@ -290,7 +290,7 @@ def removeFront(self):

![](https://qcdn.itcharge.cn/images/20211208180138.png)

因为移动到链表尾部的操作次数为`n` 次,所以该算法的时间复杂度为 $O(n)$。
因为移动到链表尾部的操作次数为 $n$ 次,所以该算法的时间复杂度为 $O(n)$。

**「链表尾部删除元素」** 的代码如下所示:

Expand All @@ -310,8 +310,8 @@ def removeRear(self):

删除链表中第 `i` 个元素的算法具体步骤如下:

- 先使用指针变量 `cur` 移动到第 `i - 1` 个位置的链节点。
- 然后将 `cur``next` 指针,指向要第 `i` 个元素的下一个节点即可。
1. 先使用指针变量 `cur` 移动到第 `i - 1` 个位置的链节点。
2. 然后将 `cur``next` 指针,指向要第 `i` 个元素的下一个节点即可。

![](https://qcdn.itcharge.cn/images/20211208180144.png)

Expand Down

0 comments on commit 4161866

Please sign in to comment.