Skip to content

Commit c796d1b

Browse files
committed
2 parents 0840d71 + 12937dd commit c796d1b

File tree

18 files changed

+138
-56
lines changed

18 files changed

+138
-56
lines changed

README.md

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44
数据结构和算法是每个程序员需要掌握的基础知识之一,也是面试中跨不过的槛。目前关于 Python 算法和数据结构的中文资料比较欠缺,
55
笔者尝试录制视频教程帮助 Python 初学者掌握常用算法和数据结构,提升开发技能。
66
本教程是付费教程(文字内容和代码免费),因为笔者录制的过程中除了购买软件、手写板等硬件之外,业余需要花费很多时间和精力来录制视频、查资料、编写课件和代码,养家糊口不容易,希望大家体谅。
7-
(视频未完成,完成后会在本页面放出链接)
87

98
## 链接
9+
视频教程已经发布在网易云课堂和 csdn 学院,内容一致,推荐使用网易云课堂。
10+
11+
[网易云课堂: Python数据结构与算法教程](http://study.163.com/course/introduction.htm?courseId=1005526003) 视频教程
12+
13+
[csdn 学院:Python数据结构与算法教程](https://edu.csdn.net/course/detail/8332)
1014

1115
[网上阅读《Python 算法与数据结构教程 》](http://ningning.today/python_data_structures_and_algorithms/)
1216

@@ -20,7 +24,7 @@
2024
- 讲 Python 数据结构和算法的资料很少,中文资料更少
2125
- 很多自学 Python 的工程师对基础不够重视,面试也发现很多数据结构和算法不过关,很多人挂在了基础的数据结构和算法上
2226
- 缺少工程应用场景下的讲解,很多讲算法的资料太『教科书化』。本书实现的代码工程上可用
23-
- 网上很多视频教程比较水,收费还很不合理,纯属智商税
27+
- 网上很多视频教程不够循序渐进,不成系统
2428

2529
## 作者简介
2630
目前就职于[知乎](https://www.zhihu.com/people/pegasus-wang/activities),任后端工程师,多年 Python 开发经验。
@@ -73,31 +77,32 @@
7377
- 面试笔试常考算法
7478

7579
## 编程语言
76-
我们这里使用最近很火的Python。Python 入门简单而且是个多面手,在爬虫、web 后端、运维、数据分析、AI 方面领域都有 Python 的身影。
80+
我们这里使用最近很火的Python。Python 入门简单而且是个多面手,在爬虫、web 后端、运维、数据分析、AI、量化投资等领域都有 Python 的身影,
81+
无论是否是专业程序员, Python 都是一门学习性价比非常高的语言。
7782
知乎、豆瓣、头条、饿了么、搜狐等公司都有广泛使用 Python。笔者日常工作使用也是 Python,有一定实践经验,
7883
在知乎上维护了一个专栏[《Python 学习之路》](https://zhuanlan.zhihu.com/c_85234576)
7984

8085
Python 抽象程度比较高, 我们能用更少的代码来实现功能,同时不用像 C/C++ 那样担心内存管理、指针操作等底层问题,
8186
把主要心思放在算法逻辑本身而不是语言细节上,Python 也号称伪代码语言。所有代码示例使用 Python2/3 兼容代码,
82-
不过只在 python3.5 下测试过,推荐用相同版本 Python。
87+
不过只在 python3.5 下测试过,推荐用相同版本 Python 进行代码编写和测试
8388

8489
## 受众
8590
想要学习 Python 算法和数据结构的初、中级同学,包括自学的同学和本科低年级学生等。需要掌握 Python
8691
的基本语法和面向对象编程的一些概念,我们这里只使用最基本的 Python 语法,不会再去介绍用到的 Python 语法糖。
8792

8893
# 预备知识
89-
- 掌握 Python 基本语法,有过使用 Python 的经验。知道 class、module、yield 等
94+
- 有一定的 python 基础,掌握 Python 基本语法,了解 python 内置数据结构的使用方式。有过使用 Python 的经验。知道 class、module、yield 等。如果是 python 初学者,建议先补补基础,否则有些部分看着会比较吃力。
9095
- 基本的面向对象编程知识,会定义和使用 Python 中的类 (class)
9196
- 知道 Python 中的魔术方法,比如 `__len__` `__contains__`
9297
- 无需太多数学基础,仅在算法时间复杂度分析的时候会用到一些简单数学知识。对于学习基础算法,逻辑思维可能更重要一些
9398

9499
## 教材
95100
这里我参考过三本书:
96101

97-
[《算法图解》](https://book.douban.com/subject/26979890/): 图解的形式很适合新手,示例使用的是 python
102+
[《算法图解》](https://book.douban.com/subject/26979890/): 图解的形式很适合新手,示例使用的是 python。建议基础较少的同学看这本书入门
98103

99104
[《Data Structures and Algorithms in Python》]( https://book.douban.com/subject/10607365/): 适合对 Python
100-
和算法比较熟悉的同学,或者是有其他语言编程经验的同学。英文版,缺点是书中错误真的很多,代码有些无法运行
105+
和算法比较熟悉的同学,或者是有其他语言编程经验的同学。本书是英文版,缺点是书中错误真的很多,代码有些无法运行而且不够 Pythonic。
101106

102107
[《算法导论》第三版]( https://book.douban.com/subject/20432061/): 喜欢数学证明和板砖书的同学可以参考,有很多高级主题。使用伪代码
103108

@@ -128,7 +133,7 @@ Python 抽象程度比较高, 我们能用更少的代码来实现功能,同
128133
这是很多看了几本书没有太多业界实践经验就敢讲课的培训班老师教不了的。**知识廉价,经验无价**
129134
- 每个实现都会有单测来验证,培养良好的编码和测试习惯,传授工程经验
130135
- 结合 cpython 底层实现讲解(比如list 内存分配策略等),避免一些使用上的坑。并且会用 python 来模拟内置 dict 等的实现
131-
- 每篇讲义后有思考题和延伸阅读链接,帮助大家加深思考和理解
136+
- 每篇讲义后有思考题和延伸阅读链接,帮助大家加深思考和理解。大部分题目答案都可以网络上搜索到
132137

133138
## 资料
134139

@@ -152,9 +157,10 @@ Python 抽象程度比较高, 我们能用更少的代码来实现功能,同
152157
- Python 实现方式
153158
- 时间、空间复杂度
154159
- 使用场景,什么时候用
155-
- 自己尝试实现,如果抛开视频自己写起来有困难可以多看几次视频,一定要自己手动实现。很多面试可能会让手写
160+
- 自己尝试实现,如果抛开视频自己写起来有困难可以反复多看几次视频,一定要自己手动实现。很多面试可能会让手写
156161
- 每章讲义后边都会有我设计的几个小问题,最好能够回答上来。同时还有代码练习题,你可以挑战下自己的掌握程度。
157-
- 最好按照顺序循序渐进,每章都会有铺垫和联系
162+
- 最好按照顺序循序渐进,每章都会有铺垫和联系,后边的章节可能会使用到前面提到的数据结构
163+
- 根据自己的基础结合我列举的教材和视频学习,第一次理解不了的可以反复多看几次,多编写代码练习到熟练为止
158164

159165
## 课程目标
160166
掌握基本的算法和数据结构原理,能独立使用 Python 语言实现,能在日常开发中灵活选用数据结构。
@@ -163,22 +169,57 @@ Python 抽象程度比较高, 我们能用更少的代码来实现功能,同
163169

164170
## 工具
165171

166-
推荐使用以下工具进行开发,如果使用编辑器最好装对 应 Python 插件:
172+
推荐使用以下工具进行开发,如果使用编辑器最好装对 应 Python 插件,笔者视频演示中使用了 vim,读者可以自己挑选自己喜欢的开发工具
167173

168174
- Pycharm
169175
- Sublime
170176
- Atom
171177
- Vscode
172178
- Vim/Emacs
173179

180+
代码中使用到了 pytest 测试框架和 when-changed 文件变动监控工具(方便我们修改完代码保存后自动执行测试),你需要用 pip 安装
181+
182+
```py
183+
pip install pytest
184+
pip install when-changed
185+
```
186+
187+
视频演示里我使用到了一个简单的 test.sh 脚本文件,内容如下:
188+
189+
```sh
190+
#!/usr/bin/env bash
191+
192+
# pip install when-changed
193+
when-changed -v -r -1 -s ./ "py.test -s $1"
194+
```
195+
将以上内容放到 test.sh 文件后加上可执行权限, `chmod +x test.sh`,之后就可以用
196+
197+
```
198+
'./test.sh somefile.py'
199+
```
200+
每次我们改动了代码,就会自动执行代码里的单元测试了。pytest 会自动发现以 test 开头的函数并执行测试代码。
201+
174202

175203
## 勘误
176204

177-
输出其实也是一种再学习的过程,中途需要查看大量资料、编写讲义、视频录制、代码编写等,难免有疏漏之处。
178-
有出版社找过笔者想让我出书,一来自己对出书兴趣不大,另外感觉书籍相对视频不够直观,有错误也不能及时修改,打算直接把所有
179-
文字内容讲义放到 github 上,供大家免费查阅。
205+
输出其实也是一种再学习的过程,中途需要查看大量资料、编写讲义、视频录制、代码编写等,难免有疏漏甚至错误之处。
206+
有出版社找过笔者想让我出书,一来自己对出书兴趣不大,另外感觉书籍相对视频不够直观,有错误也不能及时修改,打算直接把所有文字内容讲义和代码等放到 github 上,供大家免费查阅。
207+
208+
如果你发现文字内容、代码内容、视频内容有错误或者有疑问,欢迎在 github 上提 issue 讨论(或者网易公开课评论区),或者直接提 Merge Request,我会尽量及时修正相关内容,防止对读者产生误导。
209+
同时非常感谢认真学习并及时发现书中错误的同学,非常欢迎针对知识本身的交流和讨论,任何建议和修正我都会认真求证。
210+
对于提出修正意见或者提交代码的同学,由于人数比较多这里就不一一列举了,可以在以下列表查看,再次感谢你们。笔者信奉开源精神,『眼睛足够多,bug 无处藏』。
180211

181-
如果你觉得文字内容或者视频内容有错误,欢迎在 github 上提 issue 讨论,我会修正相关内容,防止产生误导。
212+
[issue](https://github.com/PegasusWang/python_data_structures_and_algorithms/issues?q=is%3Aissue+is%3Aclosed)
213+
214+
[contributors](https://github.com/PegasusWang/python_data_structures_and_algorithms/graphs/contributors)
215+
216+
## 如何提问?
217+
如果读者关于代码、视频、讲义有任何疑问,欢迎一起讨论
218+
请注意以下几点:
219+
220+
- 优先在网易云课堂的讨论区提问,方便别的同学浏览。如果未购买视频,也可以直接在 github 里提出 issue,笔者会有空会给大家解答。
221+
- 描述尽量具体,视频或者代码哪一部分有问题?
222+
- 如果涉及到代码,提问时请保持代码的格式
182223

183224

184225
## 本电子书制作和写作方式
@@ -203,7 +244,6 @@ mkdocs serve # 修改自动更新,浏览器打开 http://localhost:8000
203244
# 数学公式参考 https://www.zybuluo.com/codeep/note/163962
204245
mkdocs gh-deploy # 部署到自己的 github pages
205246
```
247+
扫码加入课程:
206248

207-
您的打赏就是我写作的最大动力,呵呵哒!
208-
209-
![微信打赏](http://7ktuty.com1.z0.glb.clouddn.com/weixin_dashang.png)
249+
![扫码加入课程返现30%](http://7ktuty.com1.z0.glb.clouddn.com/Screen%20Shot%202018-06-02%20at%2020.37.46.png)

docs/00_课程简介之笨方法学算法/why_and_how_to_learn.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
程序 = 算法 + 数据结构
66

7-
算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。
7+
算法(Algorithm):是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。
8+
89
数据结构(Data Structures):是计算机存储和组织数据的一种方式,可以用来高效地处理数据。
910

1011
举个例子:二分查找就是一个非常经典的算法,而二分查找经常需要作用在一个有序数组上。这里二分就是一种折半的算法思想,

docs/02_数组和列表/array_and_list.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Python 的 array 是内存连续、存储的都是同一数据类型的结构,
2424

2525
操作 | 平均时间复杂度 |
2626
--------------------------------------|----------------|
27-
list[index]| O(1) |
27+
list[index] | O(1) |
2828
list.append | O(1) |
2929
list.insert | O(n) |
3030
list.pop(index), default last element | O(1) |
@@ -48,3 +48,7 @@ list.remove | O(n) |
4848
[Python list implementation](https://www.laurentluce.com/posts/python-list-implementation/)
4949

5050
[https://github.com/python/cpython/blob/master/Objects/listobject.c](https://github.com/python/cpython/blob/master/Objects/listobject.c)
51+
52+
53+
# 勘误
54+
视频里的 Array.clear 方法有误。应该是 `for i in range(len(self._items))`,已经在后续所有使用到 Array 的代码里修正

docs/02_数组和列表/array_and_list.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def __len__(self):
2727
return self._size
2828

2929
def clear(self, value=None):
30-
for i in range(self._items):
30+
for i in range(len(self._items)):
3131
self._items[i] = value
3232

3333
def __iter__(self):

docs/03_链表/linked_list.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
# 单链表
1515
和线性结构不同,链式结构内存不连续的,而是一个个串起来的,这个时候就需要每个链接表的节点保存一个指向下一个节点的指针。
16+
这里可不要混淆了列表和链表(它们的中文发音类似,但是列表 list 底层其实还是线性结构,链表才是真的通过指针关联的链式结构)。
1617
看到指针你也不用怕,这里我们用的 python,你只需要一个简单赋值操作就能实现,不用担心 c 语言里复杂的指针。
1718

1819
先来定义一个链接表的节点,刚才说到有一个指针保存下一个节点的位置,我们叫它 next, 当然还需要一个 value 属性保存值
@@ -85,3 +86,7 @@ cdll.tailnode() | O(1) |
8586
# 相关阅读
8687

8788
[那些年,我们一起跪过的算法题- Lru cache[视频]](https://zhuanlan.zhihu.com/p/35175401)
89+
90+
# 勘误:
91+
92+
视频中 LinkedList.remove 方法讲解有遗漏, linked_list.py 文件已经修正,请读者注意。具体请参考 [fix linked_list & add gitigonre](https://github.com/PegasusWang/python_data_structures_and_algorithms/pull/3)。视频最后增加了一段勘误说明。

docs/03_链表/linked_list.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ def append(self, value): # O(1)
4343
self.length += 1
4444

4545
def appendleft(self, value):
46+
if self.maxsize is not None and len(self) >= self.maxsize:
47+
raise Exception('LinkedList is Full')
4648
headnode = self.root.next
4749
node = Node(value)
4850
self.root.next = node
@@ -59,21 +61,25 @@ def iter_node(self):
5961
while curnode is not self.tailnode: # 从第一个节点开始遍历
6062
yield curnode
6163
curnode = curnode.next # 移动到下一个节点
62-
yield curnode
64+
if curnode is not None:
65+
yield curnode
6366

6467
def remove(self, value): # O(n)
6568
""" 删除包含值的一个节点,将其前一个节点的 next 指向被查询节点的下一个即可
6669
6770
:param value:
6871
"""
6972
prevnode = self.root #
70-
curnode = self.root.next
7173
for curnode in self.iter_node():
7274
if curnode.value == value:
7375
prevnode.next = curnode.next
76+
if curnode is self.tailnode: # NOTE: 注意更新 tailnode
77+
self.tailnode = prevnode
7478
del curnode
7579
self.length -= 1
7680
return 1 # 表明删除成功
81+
else:
82+
prevnode = curnode
7783
return -1 # 表明删除失败
7884

7985
def find(self, value): # O(n)
@@ -97,6 +103,9 @@ def popleft(self): # O(1)
97103
self.root.next = headnode.next
98104
self.length -= 1
99105
value = headnode.value
106+
107+
if self.tailnode is headnode: # 勘误:增加单节点删除 tailnode 处理
108+
self.tailnode = None
100109
del headnode
101110
return value
102111

@@ -105,6 +114,7 @@ def clear(self):
105114
del node
106115
self.root.next = None
107116
self.length = 0
117+
self.tailnode = None
108118

109119

110120
def test_linked_list():
@@ -113,29 +123,48 @@ def test_linked_list():
113123
ll.append(0)
114124
ll.append(1)
115125
ll.append(2)
126+
ll.append(3)
116127

117-
assert len(ll) == 3
128+
assert len(ll) == 4
118129
assert ll.find(2) == 2
119-
assert ll.find(3) == -1
130+
assert ll.find(-1) == -1
120131

121132
assert ll.remove(0) == 1
122-
assert ll.remove(3) == -1
133+
assert ll.remove(10) == -1
134+
assert ll.remove(2) == 1
123135
assert len(ll) == 2
136+
assert list(ll) == [1, 3]
124137
assert ll.find(0) == -1
125138

126-
assert list(ll) == [1, 2]
127-
128139
ll.appendleft(0)
129-
assert list(ll) == [0, 1, 2]
140+
assert list(ll) == [0, 1, 3]
130141
assert len(ll) == 3
131142

132143
headvalue = ll.popleft()
133144
assert headvalue == 0
134145
assert len(ll) == 2
135-
assert list(ll) == [1, 2]
146+
assert list(ll) == [1, 3]
147+
148+
assert ll.popleft() == 1
149+
assert list(ll) == [3]
150+
ll.popleft()
151+
assert len(ll) == 0
152+
assert ll.tailnode is None
136153

137154
ll.clear()
138155
assert len(ll) == 0
156+
assert list(ll) == []
157+
158+
159+
def test_linked_list_remove():
160+
ll = LinkedList()
161+
ll.append(3)
162+
ll.append(4)
163+
ll.append(5)
164+
ll.append(6)
165+
ll.append(7)
166+
ll.remove(7)
167+
print(list(ll))
139168

140169

141170
if __name__ == '__main__':

docs/04_队列/array_queue.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def __len__(self):
1818
return self._size
1919

2020
def clear(self, value=None):
21-
for i in range(self._items):
21+
for i in range(len(self._items)):
2222
self._items[i] = value
2323

2424
def __iter__(self):
@@ -40,7 +40,7 @@ def __init__(self, maxsize):
4040
def push(self, value):
4141
if len(self) >= self.maxsize:
4242
raise FullError('queue full')
43-
self.array[self.head] = value
43+
self.array[self.head % self.maxsize] = value
4444
self.head += 1
4545

4646
def pop(self):
@@ -49,7 +49,7 @@ def pop(self):
4949
return value
5050

5151
def __len__(self):
52-
return self.head-self.tail
52+
return self.head - self.tail
5353

5454

5555
def test_queue():
@@ -68,10 +68,13 @@ def test_queue():
6868
assert q.pop() == 0
6969
assert q.pop() == 1
7070

71-
assert len(q) == 3
71+
q.push(5)
72+
73+
assert len(q) == 4
7274

7375
assert q.pop() == 2
7476
assert q.pop() == 3
7577
assert q.pop() == 4
78+
assert q.pop() == 5
7679

7780
assert len(q) == 0

docs/04_队列/queue.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,15 @@ def remove(self, value): # O(n)
6969
"""
7070
prevnode = self.root #
7171
curnode = self.root.next
72-
while curnode.next is not None:
72+
for curnode in self.iter_node():
7373
if curnode.value == value:
7474
prevnode.next = curnode.next
7575
del curnode
7676
self.length -= 1
77-
return
77+
return 1 # 表明删除成功
78+
else:
79+
prevnode = curnode
80+
return -1 # 表明删除失败
7881

7982
def find(self, value): # O(n)
8083
""" 查找一个节点,返回序号,从 0 开始

0 commit comments

Comments
 (0)