Skip to content
This repository was archived by the owner on Apr 11, 2021. It is now read-only.

merge from origin #1

Merged
merged 38 commits into from
Jul 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0e65436
spell error
PegasusWang May 29, 2018
9e3b512
spell error
PegasusWang May 29, 2018
2b1e1fa
Merge pull request #3 from Ehco1996/fix-linked-list
PegasusWang May 29, 2018
265d6df
增加网易云课堂视频教程链接
PegasusWang May 29, 2018
1c56335
链接表勘误:LinedList.remove 实现有 bug
PegasusWang May 29, 2018
d074b89
勘误:Array.clear 方法有误
PegasusWang May 29, 2018
feb9991
fix https://github.com/PegasusWang/python_data_structures_and_algorit…
May 31, 2018
d578958
修正 LinkList.remove 方法没有更新 prevnode 的 bug
PegasusWang Jun 1, 2018
0c51b9a
Merge branch 'master' of github.com:PegasusWang/python_data_structure…
PegasusWang Jun 1, 2018
ae0add1
勘误说明
PegasusWang Jun 1, 2018
8d35f95
change readme
PegasusWang Jun 1, 2018
49aa5ae
勘误说明;readme
PegasusWang Jun 2, 2018
4fad096
网易云二维码
PegasusWang Jun 2, 2018
7629faf
修复一个拼写错误
hjlarry Jun 4, 2018
1acb16b
fix LinkedList remove tailnode
Jun 4, 2018
57c1281
Merge pull request #6 from hjlarry/master
PegasusWang Jun 4, 2018
d18d5ea
array_queue fix
PegasusWang Jun 6, 2018
17bf91d
预备知识说明
PegasusWang Jun 6, 2018
2526f07
update readme
PegasusWang Jun 6, 2018
134035b
修复二叉树文档内代码缩进错误
hjlarry Jun 7, 2018
448a890
修复 set 交集方法
PegasusWang Jun 9, 2018
f673f3f
Merge pull request #7 from hjlarry/master
PegasusWang Jun 9, 2018
6110054
修复bst中删除节点时的代码错误
hjlarry Jun 9, 2018
1e988a7
补充安装 pytest 和 when-changed
PegasusWang Jun 10, 2018
ca39307
Merge branch 'master' of github.com:PegasusWang/python_data_structure…
PegasusWang Jun 10, 2018
626511e
Merge pull request #8 from hjlarry/master
PegasusWang Jun 10, 2018
8c62580
update readme
PegasusWang Jun 10, 2018
184f8a9
Merge branch 'master' of github.com:PegasusWang/python_data_structure…
PegasusWang Jun 10, 2018
ff3cd19
bst 勘误
PegasusWang Jun 10, 2018
6325916
bst 删除俩孩子注释
PegasusWang Jun 10, 2018
74a0d38
update test.sh
PegasusWang Jun 10, 2018
5628b0e
hash and set 文档修正
PegasusWang Jun 11, 2018
69622b0
修正 LinkList.remove 无用的 curnode 定义;更新 readme 如何提问
PegasusWang Jun 16, 2018
154168f
bugfix: http://study.163.com/forum/detail/1004978058.htm
PegasusWang Jun 24, 2018
4e6c352
fix format
PegasusWang Jun 27, 2018
07ad56e
修复 链表 clear 和 iter_node bug
PegasusWang Jul 10, 2018
58d5d21
复修 链表判断是否达到最大 size 的问题
PegasusWang Jul 10, 2018
5c900f2
增加勘误和贡献者名单网址
PegasusWang Jul 10, 2018
File filter

Filter by extension

Filter by extension

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

## 链接
视频教程已经发布在网易云课堂和 csdn 学院,内容一致,推荐使用网易云课堂。

[网易云课堂: Python数据结构与算法教程](http://study.163.com/course/introduction.htm?courseId=1005526003) 视频教程

[csdn 学院:Python数据结构与算法教程](https://edu.csdn.net/course/detail/8332)

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

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

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

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

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

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

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

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

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

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

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

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

## 资料

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

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

## 工具

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

- Pycharm
- Sublime
- Atom
- Vscode
- Vim/Emacs

代码中使用到了 pytest 测试框架和 when-changed 文件变动监控工具(方便我们修改完代码保存后自动执行测试),你需要用 pip 安装

```py
pip install pytest
pip install when-changed
```

视频演示里我使用到了一个简单的 test.sh 脚本文件,内容如下:

```sh
#!/usr/bin/env bash

# pip install when-changed
when-changed -v -r -1 -s ./ "py.test -s $1"
```
将以上内容放到 test.sh 文件后加上可执行权限, `chmod +x test.sh`,之后就可以用

```
'./test.sh somefile.py'
```
每次我们改动了代码,就会自动执行代码里的单元测试了。pytest 会自动发现以 test 开头的函数并执行测试代码。


## 勘误

输出其实也是一种再学习的过程,中途需要查看大量资料、编写讲义、视频录制、代码编写等,难免有疏漏之处。
有出版社找过笔者想让我出书,一来自己对出书兴趣不大,另外感觉书籍相对视频不够直观,有错误也不能及时修改,打算直接把所有
文字内容讲义放到 github 上,供大家免费查阅。
输出其实也是一种再学习的过程,中途需要查看大量资料、编写讲义、视频录制、代码编写等,难免有疏漏甚至错误之处。
有出版社找过笔者想让我出书,一来自己对出书兴趣不大,另外感觉书籍相对视频不够直观,有错误也不能及时修改,打算直接把所有文字内容讲义和代码等放到 github 上,供大家免费查阅。

如果你发现文字内容、代码内容、视频内容有错误或者有疑问,欢迎在 github 上提 issue 讨论(或者网易公开课评论区),或者直接提 Merge Request,我会尽量及时修正相关内容,防止对读者产生误导。
同时非常感谢认真学习并及时发现书中错误的同学,非常欢迎针对知识本身的交流和讨论,任何建议和修正我都会认真求证。
对于提出修正意见或者提交代码的同学,由于人数比较多这里就不一一列举了,可以在以下列表查看,再次感谢你们。笔者信奉开源精神,『眼睛足够多,bug 无处藏』。

如果你觉得文字内容或者视频内容有错误,欢迎在 github 上提 issue 讨论,我会修正相关内容,防止产生误导。
[issue](https://github.com/PegasusWang/python_data_structures_and_algorithms/issues?q=is%3Aissue+is%3Aclosed)

[contributors](https://github.com/PegasusWang/python_data_structures_and_algorithms/graphs/contributors)

## 如何提问?
如果读者关于代码、视频、讲义有任何疑问,欢迎一起讨论
请注意以下几点:

- 优先在网易云课堂的讨论区提问,方便别的同学浏览。如果未购买视频,也可以直接在 github 里提出 issue,笔者会有空会给大家解答。
- 描述尽量具体,视频或者代码哪一部分有问题?
- 如果涉及到代码,提问时请保持代码的格式


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

您的打赏就是我写作的最大动力,呵呵哒!

![微信打赏](http://7ktuty.com1.z0.glb.clouddn.com/weixin_dashang.png)
![扫码加入课程返现30%](http://7ktuty.com1.z0.glb.clouddn.com/Screen%20Shot%202018-06-02%20at%2020.37.46.png)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

程序 = 算法 + 数据结构

算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。
算法(Algorithm):是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。

数据结构(Data Structures):是计算机存储和组织数据的一种方式,可以用来高效地处理数据。

举个例子:二分查找就是一个非常经典的算法,而二分查找经常需要作用在一个有序数组上。这里二分就是一种折半的算法思想,
Expand Down
6 changes: 5 additions & 1 deletion docs/02_数组和列表/array_and_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Python 的 array 是内存连续、存储的都是同一数据类型的结构,

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

[https://github.com/python/cpython/blob/master/Objects/listobject.c](https://github.com/python/cpython/blob/master/Objects/listobject.c)


# 勘误
视频里的 Array.clear 方法有误。应该是 `for i in range(len(self._items))`,已经在后续所有使用到 Array 的代码里修正
2 changes: 1 addition & 1 deletion docs/02_数组和列表/array_and_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __len__(self):
return self._size

def clear(self, value=None):
for i in range(self._items):
for i in range(len(self._items)):
self._items[i] = value

def __iter__(self):
Expand Down
5 changes: 5 additions & 0 deletions docs/03_链表/linked_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

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

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

[那些年,我们一起跪过的算法题- Lru cache[视频]](https://zhuanlan.zhihu.com/p/35175401)

# 勘误:

视频中 LinkedList.remove 方法讲解有遗漏, linked_list.py 文件已经修正,请读者注意。具体请参考 [fix linked_list & add gitigonre](https://github.com/PegasusWang/python_data_structures_and_algorithms/pull/3)。视频最后增加了一段勘误说明。
49 changes: 39 additions & 10 deletions docs/03_链表/linked_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __len__(self):
return self.length

def append(self, value): # O(1)
if self.maxsize is not None and len(self) > self.maxsize:
if self.maxsize is not None and len(self) >= self.maxsize:
raise Exception('LinkedList is Full')
node = Node(value) # 构造节点
tailnode = self.tailnode
Expand All @@ -43,6 +43,8 @@ def append(self, value): # O(1)
self.length += 1

def appendleft(self, value):
if self.maxsize is not None and len(self) >= self.maxsize:
raise Exception('LinkedList is Full')
headnode = self.root.next
node = Node(value)
self.root.next = node
Expand All @@ -59,21 +61,25 @@ def iter_node(self):
while curnode is not self.tailnode: # 从第一个节点开始遍历
yield curnode
curnode = curnode.next # 移动到下一个节点
yield curnode
if curnode is not None:
yield curnode

def remove(self, value): # O(n)
""" 删除包含值的一个节点,将其前一个节点的 next 指向被查询节点的下一个即可

:param value:
"""
prevnode = self.root #
curnode = self.root.next
for curnode in self.iter_node():
if curnode.value == value:
prevnode.next = curnode.next
if curnode is self.tailnode: # NOTE: 注意更新 tailnode
self.tailnode = prevnode
del curnode
self.length -= 1
return 1 # 表明删除成功
else:
prevnode = curnode
return -1 # 表明删除失败

def find(self, value): # O(n)
Expand All @@ -97,6 +103,9 @@ def popleft(self): # O(1)
self.root.next = headnode.next
self.length -= 1
value = headnode.value

if self.tailnode is headnode: # 勘误:增加单节点删除 tailnode 处理
self.tailnode = None
del headnode
return value

Expand All @@ -105,6 +114,7 @@ def clear(self):
del node
self.root.next = None
self.length = 0
self.tailnode = None


def test_linked_list():
Expand All @@ -113,29 +123,48 @@ def test_linked_list():
ll.append(0)
ll.append(1)
ll.append(2)
ll.append(3)

assert len(ll) == 3
assert len(ll) == 4
assert ll.find(2) == 2
assert ll.find(3) == -1
assert ll.find(-1) == -1

assert ll.remove(0) == 1
assert ll.remove(3) == -1
assert ll.remove(10) == -1
assert ll.remove(2) == 1
assert len(ll) == 2
assert list(ll) == [1, 3]
assert ll.find(0) == -1

assert list(ll) == [1, 2]

ll.appendleft(0)
assert list(ll) == [0, 1, 2]
assert list(ll) == [0, 1, 3]
assert len(ll) == 3

headvalue = ll.popleft()
assert headvalue == 0
assert len(ll) == 2
assert list(ll) == [1, 2]
assert list(ll) == [1, 3]

assert ll.popleft() == 1
assert list(ll) == [3]
ll.popleft()
assert len(ll) == 0
assert ll.tailnode is None

ll.clear()
assert len(ll) == 0
assert list(ll) == []


def test_linked_list_remove():
ll = LinkedList()
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
ll.append(7)
ll.remove(7)
print(list(ll))


if __name__ == '__main__':
Expand Down
11 changes: 7 additions & 4 deletions docs/04_队列/array_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __len__(self):
return self._size

def clear(self, value=None):
for i in range(self._items):
for i in range(len(self._items)):
self._items[i] = value

def __iter__(self):
Expand All @@ -40,7 +40,7 @@ def __init__(self, maxsize):
def push(self, value):
if len(self) >= self.maxsize:
raise FullError('queue full')
self.array[self.head] = value
self.array[self.head % self.maxsize] = value
self.head += 1

def pop(self):
Expand All @@ -49,7 +49,7 @@ def pop(self):
return value

def __len__(self):
return self.head-self.tail
return self.head - self.tail


def test_queue():
Expand All @@ -68,10 +68,13 @@ def test_queue():
assert q.pop() == 0
assert q.pop() == 1

assert len(q) == 3
q.push(5)

assert len(q) == 4

assert q.pop() == 2
assert q.pop() == 3
assert q.pop() == 4
assert q.pop() == 5

assert len(q) == 0
7 changes: 5 additions & 2 deletions docs/04_队列/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,15 @@ def remove(self, value): # O(n)
"""
prevnode = self.root #
curnode = self.root.next
while curnode.next is not None:
for curnode in self.iter_node():
if curnode.value == value:
prevnode.next = curnode.next
del curnode
self.length -= 1
return
return 1 # 表明删除成功
else:
prevnode = curnode
return -1 # 表明删除失败

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