Skip to content

Commit cc0a5cc

Browse files
committed
更新链表章节和 README 章节
1 parent 2f8709b commit cc0a5cc

File tree

2 files changed

+16
-17
lines changed

2 files changed

+16
-17
lines changed

3_链表/linked_list.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# 链式结构
22

3-
上一节讲到了支持随机访问的线性结构,这次我们开始讲链式结构。最常见的就是单链表和双链表
3+
上一节讲到了支持随机访问的线性结构,这次我们开始讲链式结构, 视频里我会说下这两种结构的区别,然后讲解最常见的单链表和双链表
44
之前在专栏文章[那些年,我们一起跪过的算法题[视频]](https://zhuanlan.zhihu.com/p/35175401)里实现过一个 lru_cache,
55
使用到的就是循环双端链表,如果感觉这篇文章有点难理解,我们这里将会循序渐进地来实现。
6-
后边讲到哈希表的冲突解决方式的时候,我们会再次使用链接表
6+
后边讲到哈希表的冲突解决方式的时候,我们会再次提到链表
77

88
上一节我们分析了 list 的各种操作是如何实现的,如果你还有印象的话,list
99
在头部进行插入是个相当耗时的操作(需要把后边的元素一个一个挪个位置)。假如你需要频繁在数组两头增删,list 就不太合适。
10-
今天我们介绍的链式结构将摆脱这个缺陷,当然了链式结构本身也有缺陷,比如你不能像数组一样随机根据下标访问。
10+
今天我们介绍的链式结构将摆脱这个缺陷,当然了链式结构本身也有缺陷,比如你不能像数组一样随机根据下标访问,你想查找一个元素只能老老实实从头遍历
1111
所以嘛,学习和了解数据结构的原理和实现你才能准确地选择到底什么时候该用什么数据结构,而不是瞎选导致代码性能很差。
1212

1313

@@ -31,24 +31,24 @@ class LinkedList(object):
3131
[root] -> [node0] -> [node1] -> [node2]
3232
"""
3333
```
34-
实现我们会在视频中用画图来模拟并且手动代码实现
34+
实现我们会在视频中用画图来模拟并且手动代码实现,代码里我们会标识每个步骤的时间复杂度.
3535

3636
来看下时间复杂度:
3737

38-
操作 | 平均时间复杂度 |
39-
--------------------------|----------------|
40-
linked_list.append(value) | O(1) |
38+
操作 | 平均时间复杂度 |
39+
------------------------------|----------------|
40+
linked_list.append(value) | O(1) |
4141
linked_list.appendleft(value) | O(1) |
42-
linked_list.find(value) | O(n) |
43-
linked_list.remove(value) | O(n) |
42+
linked_list.find(value) | O(n) |
43+
linked_list.remove(value) | O(n) |
4444

4545

4646
# 双链表
4747
上边我们亲自实现了一个单链表,但是能看到很明显的问题,单链表虽然 append 是 O(1),但是它的 find 和 remove 都是 O(n)的,
4848
因为删除你也需要先查找,而单链表查找只有一个方式就是从头找到尾,中间找到才退出。
49-
这里我之前提到过如果要实现一个 lru
50-
缓存(访问时间最久的踢出),我们需要在一个链表里能高效的删除元素,并把它追加到访问表的最后一个位置,这个时候单链表就满足不了了,
51-
因为缓存在dict 里查找的时间是 O(1),你更新访问顺序就 O(n)了,缓存就没了优势。
49+
这里我之前提到过如果要实现一个 lru 缓存(访问时间最久的踢出),我们需要在一个链表里能高效的删除元素,
50+
并把它追加到访问表的最后一个位置,这个时候单链表就满足不了了,
51+
因为缓存在 dict 里查找的时间是 O(1),你更新访问顺序就 O(n)了,缓存就没了优势。
5252

5353
这里就要使用到双链表了,相比单链表来说,每个节点既保存了指向下一个节点的指针,同时还保存了上一个节点的指针。
5454

@@ -63,14 +63,13 @@ class Node(object):
6363

6464
- 看似我们反过来遍历双链表了。反过来从哪里开始呢?我们只要让 root 的 prev 指向 tail 节点,不就串起来了吗?
6565
- 直接删除节点,当然如果给的是一个值,我们还是需要查找这个值在哪个节点? - 但是如果给了一个节点,我们把它拿掉,直接让它的前后节点互相指过去不就行了?哇欧,删除就是 O(1) 了,两步操作就行啦
66-
- 是不是可以很方便地
6766

6867
好,废话不多说,我们在视频里介绍怎么实现一个双链表 ADT。
6968

7069

7170
# 小问题:
7271
- 这里单链表我没有实现 insert 方法,你能自己尝试实现吗? insert(value, new_value),我想在某个值之前插入一个值。你同样需要先查找,所以这个步骤也不够高效。
73-
- 你能尝试自己实现个 lru cache 吗?
72+
- 你能尝试自己实现个 lru cache 吗?需要使用到我们这里提到的循环双端队列
7473
- python 内置库的哪些数据结构使用到了本章讲的链式结构?
7574

7675
# 相关阅读

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
## 痛点
99
- 讲 Python 数据结构和算法的资料很少,中文资料更少
10-
- 很多自学 Python 的工程师对基础不够重视,面试也发现很多数据结构和算法不过关
10+
- 很多自学 Python 的工程师对基础不够重视,面试也发现很多数据结构和算法不过关,太多人挂在了基础的数据结构和算法上
1111
- 缺少工程应用场景下的讲解,很多讲算法的资料太『教科书化』
1212
- 很多培训班出来的同学或者自学的同学数据结构和算法比较薄弱,面试笔试很吃亏
1313

@@ -112,7 +112,7 @@ Python 抽象程度比较高, 我们能用更少的代码来实现功能,同
112112
- 良好的工程实践:[编码之前碎碎念(工程实践)](http://python-web-guide.readthedocs.io/zh/latest/codingstyle/codingstyle.html)
113113
这是很多看了几本书没有太多业界实践经验就敢讲课的培训班老师教不了的。**知识廉价,经验无价**
114114
- 每个实现都会有单测来验证,培养良好的编码和测试习惯,传授工程经验
115-
- 结合 cpython 底层实现讲解(比如list 内存分配策略等),避免一些使用上的坑
115+
- 结合 cpython 底层实现讲解(比如list 内存分配策略等),避免一些使用上的坑。并且会用 python 来模拟内置 dict 等的实现
116116
- 每篇讲义后有思考题和延伸阅读链接,帮助大家加深思考和理解
117117

118118
## 资料
@@ -158,4 +158,4 @@ Python 抽象程度比较高, 我们能用更少的代码来实现功能,同
158158
有出版社找过笔者想让我出书,一来自己对出书兴趣不大,另外感觉书籍相对视频不够直观,有错误也不能及时修改,打算直接把所有
159159
文字内容讲义放到 github 上,供大家免费查阅。
160160

161-
如果你觉得文字内容或者视频内容有错误,欢迎在github 上提 issue 讨论,我会修正相关内容,防止产生误导。
161+
如果你觉得文字内容或者视频内容有错误,欢迎在 github 上提 issue 讨论,我会修正相关内容,防止产生误导。

0 commit comments

Comments
 (0)