Skip to content

Commit 30d4848

Browse files
committed
Update 01.Linked-List-Basic.md
1 parent 8928619 commit 30d4848

File tree

1 file changed

+37
-30
lines changed

1 file changed

+37
-30
lines changed

Contents/02.Linked-List/01.Linked-List-Basic/01.Linked-List-Basic.md

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

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

11-
![](https://qcdn.itcharge.cn/images/20211205151319.png)
11+
![](https://qcdn.itcharge.cn/images/20211208180037.png)
1212

13-
如上图所示,链表通过将一组任意的存储单元串联在一起。其中,每个数据元素占用若干存储单元的组合称为一个「链节点」。为了将所有的节点串起来,每个链节点不仅要存放一个数据元素的数据信息,还要存放一个指出这个数据元素在逻辑关系上的直接后继元素所在链节点的地址,该地址被称为「后继指针 `next`」。
13+
如上图所示,链表通过将一组任意的存储单元串联在一起。其中,每个数据元素占用若干存储单元的组合称为一个「链节点」。为了将所有的节点串起来,每个链节点不仅要存放一个数据元素的值,还要存放一个指出这个数据元素在逻辑关系上的直接后继元素所在链节点的地址,该地址被称为「后继指针 `next`」。
1414

1515
在链表中,数据元素之间的逻辑关系是通过指针来间接反映的。逻辑上相邻的数据元素在物理地址上可能相邻,可也能不相邻。其在物理地址上的表现是随机的。
1616

@@ -36,7 +36,7 @@
3636
3737
从循环链表的任何一个节点出发都能找到任何其他节点。
3838

39-
![](https://qcdn.itcharge.cn/images/20211208103712.png)
39+
![](https://qcdn.itcharge.cn/images/20211208180048.png)
4040

4141
接下来我们以单链表为例,介绍一下链表的基本操作。
4242

@@ -73,7 +73,7 @@ class LinkedList:
7373
- 每获取一个数据元素,就为该数据元素生成一个新节点,将新节点插入到链表的尾部。
7474
- 插入完毕之后返回第 `1` 个链节点的地址。
7575

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

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

@@ -133,22 +133,24 @@ def find(self, val):
133133

134134
### 2.5 插入元素
135135

136-
插入元素操作分为三种
136+
链表中插入元素操作分为三种
137137

138-
- 头部插入元素:在链表第 `1` 个链节点之前插入值为 `val` 的链节点。
139-
- 尾部插入元素:在链表尾部插入值为 `val` 的链节点。
140-
- 中间插入元素:在链表第 `i` 个链节点之前插入值为 `val` 的链节点。
138+
- 链表头部插入元素:在链表第 `1` 个链节点之前插入值为 `val` 的链节点。
139+
- 链表尾部插入元素:在链表尾部插入值为 `val` 的链节点。
140+
- 链表中间插入元素:在链表第 `i` 个链节点之前插入值为 `val` 的链节点。
141141

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

144-
#### 2.5.1 头部插入元素
144+
#### 2.5.1 链表头部插入元素
145145

146146
算法实现的步骤为:
147147

148148
- 先创建一个值为 `val` 的链节点 `node`
149149
- 然后将 `node``next` 指针指向链表的头节点 `head`
150150
- 再将链表的头节点 `head ` 指向 `node`
151151

152+
![](https://qcdn.itcharge.cn/images/20211208180101.png)
153+
152154
因为在链表头部插入链节点与链表的长度无关,所以该算法的时间复杂度为 $O(1)$。
153155

154156
**「在链表头部插入值为 `val` 元素」** 的代码如下:
@@ -170,6 +172,8 @@ def insertFront(self, val):
170172
- 通过链节点的 `next` 指针移动 `cur` 指针,从而遍历链表,直到 `cur.next == None`
171173
-`cur.next` 指向将新的链节点 `node`
172174

175+
![](https://qcdn.itcharge.cn/images/20211208180111.png)
176+
173177
因为将 `cur` 从链表头部移动到尾部的操作次数是 `n` 次,所以该算法的时间复杂度是 $O(n)$。
174178

175179
**「在链表尾部插入值为 `val` 的元素」** 的代码如下:
@@ -191,9 +195,12 @@ def insertRear(self, val):
191195
- 使用指针变量 `cur` 和一个计数器 `count`。令 `cur` 指向链表的头节点,`count` 初始值赋值为 `0`
192196
- 沿着链节点的 `next` 指针遍历链表,指针变量 `cur` 每指向一个链节点,计数器就做一次计数。
193197
-`count == index - 1` 时,说明遍历到了第 `index - 1` 个链节点,此时停止遍历。
198+
- 创建一个值为 `val` 的链节点 `node`
194199
-`node.next` 指向 `cur.next`
195200
- 然后令 `cur.next` 指向 `node`
196201

202+
![](https://qcdn.itcharge.cn/images/20211208180121.png)
203+
197204
因为将 `cur` 从链表头部移动到第 `i` 个链节点之前的操作平均时间复杂度是 $O(n)$,所以该算法的时间复杂度是 $O(n)$。
198205

199206
**「在链表第 `i` 个链节点之前插入值为 `val` 的元素」** 的代码如下:
@@ -247,42 +254,46 @@ def change(self, index, val):
247254

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

250-
- 删除链表头部元素:删除链表的第 `1` 个链节点。
251-
- 删除链表尾部元素:删除链表末尾最后 `1` 个链节点。
252-
- 删除链表中间元素:删除链表第 `i` 个链节点。
257+
- 链表头部删除元素:删除链表的第 `1` 个链节点。
258+
- 链表尾部删除元素:删除链表末尾最后 `1` 个链节点。
259+
- 链表中间删除元素:删除链表第 `i` 个链节点。
253260

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

256-
#### 2.7.1 删除链表头部元素
263+
#### 2.7.1 链表头部删除元素
257264

258-
删除链表头部元素的方法很简单,具体步骤如下:
265+
链表头部删除元素的方法很简单,具体步骤如下:
259266

260267
- 直接将 `self.head` 沿着 `next` 指针向右移动一步即可。
261268

262-
因为只涉及到一步移动操作,所以此算法的时间复杂度为 $O(1)$。
269+
![](https://qcdn.itcharge.cn/images/20211208180131.png)
263270

264-
**「删除链表头部元素」** 的代码如下所示:
271+
因为只涉及到 `1` 步移动操作,所以此算法的时间复杂度为 $O(1)$。
272+
273+
**「链表头部删除元素」** 的代码如下所示:
265274

266275
```Python
267-
# 移除链表头部元素
276+
# 链表头部删除元素
268277
def removeFront(self):
269278
if self.head:
270279
self.head = self.head.next
271280
```
272281

273-
#### 2.7.2 删除链表尾部元素
282+
#### 2.7.2 链表尾部删除元素
274283

275-
删除链表尾部元素的方法也比价简单,具体步骤如下:
284+
链表尾部删除元素的方法也比价简单,具体步骤如下:
276285

277286
- 先使用指针变量 `cur` 沿着 `next` 指针移动到倒数第 `2` 个链节点。
278287
- 然后将此节点的 `next` 指针指向 `None` 即可。
279288

289+
![](https://qcdn.itcharge.cn/images/20211208180138.png)
290+
280291
因为移动到链表尾部的操作次数为`n` 次,所以该算法的时间复杂度为 $O(n)$。
281292

282-
**删除链表尾部元素** 的代码如下所示:
293+
**链表尾部删除元素** 的代码如下所示:
283294

284295
```Python
285-
# 移除链表尾部元素
296+
# 链表尾部删除元素
286297
def removeRear(self):
287298
if not self.head.next:
288299
return 'Error'
@@ -293,17 +304,19 @@ def removeRear(self):
293304
cur.next = None
294305
```
295306

296-
#### 2.7.3 删除链表中间元素
307+
#### 2.7.3 链表中间删除元素
297308

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

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

314+
![](https://qcdn.itcharge.cn/images/20211208180144.png)
315+
303316
**「删除链表中第 `i` 个元素」** 的代码如下所示:
304317

305318
```Python
306-
# 移除链表中间元素
319+
# 链表中间删除元素
307320
def removeInside(self, index):
308321
count = 0
309322
cur = self.head
@@ -327,18 +340,12 @@ def removeInside(self, index):
327340

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

330-
链表最大的优点在可以灵活的添加和删除元素。链表进行访问元素、改变元素操作的时间复杂度为 $O(n)$,进行头部插入、尾部插入、头部删除、尾部删除元素操作的时间复杂度是 $O(1)$,普通情况下进行插入、删除元素进行的时间复杂度为 $O(n)$。
343+
链表最大的优点在于可以灵活的添加和删除元素。链表进行访问元素、改变元素操作的时间复杂度为 $O(n)$,进行头部插入、尾部插入、头部删除、尾部删除元素操作的时间复杂度是 $O(1)$,普通情况下进行插入、删除元素操作的时间复杂度为 $O(n)$。
331344

332345
## 参考资料
333346

334347
- 【文章】[链表理论基础 - 代码随想录](https://programmercarl.com/链表理论基础.html#链表理论基础)
335-
336-
- 【文章】[Python 与 Java 中容器对比:List - 知乎](https://zhuanlan.zhihu.com/p/120312437)
337-
338348
- 【文章】[什么是链表 - 漫画算法 - 小灰的算法之旅 - 力扣](https://leetcode-cn.com/leetbook/read/journey-of-algorithm/5ozchs/)
339-
340349
- 【文章】[链表 - 数据结构与算法之美 - 极客时间](https://time.geekbang.org/column/article/41013)
341-
342350
- 【书籍】数据结构教程 第 2 版 - 唐发根 著
343-
344351
- 【书籍】数据结构与算法 Python 语言描述 - 裘宗燕 著

0 commit comments

Comments
 (0)