Skip to content

Commit 2c37a48

Browse files
committed
Done
1 parent 70b824c commit 2c37a48

File tree

35 files changed

+275
-275
lines changed

35 files changed

+275
-275
lines changed

README.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
- 使用場景,什麼時候用
4848

4949
## 目錄結構
50-
這裡講解的章節我参考了下邊教材中列舉的一些書籍,並且自己設計了大綱,争取做到循序漸進,簡單實用。因為實現一些高级數據結構的時候會用到
50+
這裡講解的章節我参考了下邊教材中列舉的一些書籍,並且自己設計了大綱,争取做到循序漸進,簡單實用。因為實現一些高級數據結構的時候會用到
5151
很多底層數據結構,防止跳跃太大導致讀者理解困難。
5252

5353
課程的目錄結構如下,每一章都有配套的文字講義(markdown),示例原始碼,影片講解,詳細的講解一般會放在影片裡,使用手寫板來
@@ -57,7 +57,7 @@
5757
- 課程簡介之笨方法學算法
5858
- 抽象數據類型 ADT,面向對象編程
5959
- 數组和列表
60-
- 鏈表,高级鏈表。双鏈表,循環双端鏈表
60+
- 鏈表,高級鏈表。双鏈表,循環双端鏈表
6161
- 陣列,双端陣列,循環双端陣列
6262
- 堆疊,堆疊溢出
6363
- 算法分析,時間複雜度 大O 表示法
@@ -67,17 +67,17 @@
6767
- 遞迴
6868
- 查找:線性查找和二分查找
6969
- 基本排序算法: 冒泡、選择、插入排序
70-
- 高级排序算法: 归並排序、快排
70+
- 高級排序算法: 归並排序、快排
7171
- 樹,二元樹
7272
- 堆與堆排序
73-
- 優先级陣列
73+
- 優先級陣列
7474
- 二元查找樹
7575
- 圖與圖的尋訪
7676
- python 内置常用數據結構和算法的使用。list, dict, set, collections 模块,heapq 模块
7777
- 面試筆試常考算法
7878

7979
## 編程語言
80-
我們這裡使用最近很火的Python。Python 入門簡單而且是個多面手,在爬蟲、web 後端、運维、數據分析、AI、量化投資等領域都有 Python 的身影,
80+
我們這裡使用最近很火的Python。Python 入門簡單而且是個多面手,在爬蟲、web 後端、運維、數據分析、AI、量化投資等領域都有 Python 的身影,
8181
無論是否是專業程序員, Python 都是一門學習性價比非常高的語言。
8282
知乎、豆瓣、頭條、餓了麼、搜狐等公司都有廣泛使用 Python。筆者日常工作使用也是 Python,有一定實践經驗,
8383
在知乎上維護了一個專欄[《Python 學習之路》](https://zhuanlan.zhihu.com/c_85234576)
@@ -87,7 +87,7 @@ Python 抽象程度比較高, 我們能用更少的原始碼來實現功能,
8787
不過只在 python3.5 下測試過,推薦用相同版本 Python 進行原始碼編寫和測試。
8888

8989
## 對象
90-
想要學習 Python 算法和數據結構的中级同學,包括自學的同學和本科低年级學生等。需要掌握 Python
90+
想要學習 Python 算法和數據結構的中級同學,包括自學的同學和本科低年級學生等。需要掌握 Python
9191
的基本語法和面向對象編程的一些概念,有一定的 Python 使用經驗。我們這裡儘量只使用最基本的 Python 語法,不會再去介绍用到的 Python 語法糖。
9292
數據結構和算法算是本科教育中偏難的課程,既需要你理解其原理,又需要具有有扎實的編程能力。
9393

@@ -97,7 +97,7 @@ Python 抽象程度比較高, 我們能用更少的原始碼來實現功能,
9797
(注意:有些同學看起來很吃力,為了不花冤枉钱,我建議你先整體瀏覽本電子書的内容和原始碼是否在自己的理解範圍内,再決定是否購買影片。有些概念不是立刻就能理解的,需要反复思考實践)
9898

9999
- 了解基本的數據結構和算法的概念,不適合**完全**没有了解過算法的新手,更不適合 Python 基礎都没掌握的同學。購買之前請慎重考慮
100-
- 無需太多數學基礎,仅在算法時間複雜度分析的時候會用到一些簡單數學知識。對於學習基礎算法,邏輯思维可能更重要一些
100+
- 無需太多數學基礎,仅在算法時間複雜度分析的時候會用到一些簡單數學知識。對於學習基礎算法,邏輯思維可能更重要一些
101101

102102
## 参考教材和鏈接
103103
這裡我参考過三本書,均可以網購紙本版或者網路上搜索電子版,建議大家先大致閱讀一本教材掌握基本原理:
@@ -107,7 +107,7 @@ Python 抽象程度比較高, 我們能用更少的原始碼來實現功能,
107107
[《Data Structures and Algorithms in Python》]( https://book.douban.com/subject/10607365/): 適合對 Python
108108
和算法比較熟悉的同學,或者是有其他語言編程經驗的同學。本書是英文版,缺點是書中錯誤真的很多,原始碼有些無法運行而且不够 Pythonic。該書 [勘誤](http://bcs.wiley.com/he-bcs/Books?action=resource&bcsId=9003&itemId=0470618299&resourceId=35653)
109109

110-
[《算法導論》第三版]( https://book.douban.com/subject/20432061/): 喜欢數學證明和板砖書的同學可以参考,有很多高级主題。使用偽原始碼
110+
[《算法導論》第三版]( https://book.douban.com/subject/20432061/): 喜欢數學證明和板砖書的同學可以参考,有很多高級主題。使用偽原始碼
111111

112112
## 算法可視化
113113

@@ -153,9 +153,9 @@ https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
153153
- markdown 講義,包含影片内容的提要等内容
154154
- 延伸閱讀。我會附上一些閱讀資料方便想深入學習的同學
155155

156-
## 如何获取每章原始碼
156+
## 如何獲取每章原始碼
157157

158-
注意每一章目錄裡都有 py 文件,在電子書裡看不到。clone 下本原始碼仓库找到對應目錄裡的 python 文件即是每章涉及到的原始碼。
158+
注意每一章目錄裡都有 py 文件,在電子書裡看不到。clone 下本原始碼仓庫找到對應目錄裡的 python 文件即是每章涉及到的原始碼。
159159
由於原始碼實現千差万别,本書原始碼實現具有一定的個人風格,不代表最佳實現,仅供参考。
160160

161161

@@ -170,7 +170,7 @@ https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
170170
- 使用場景,什麼時候用
171171
- 自己嘗試實現,如果抛開影片自己寫起來有困難可以反复多看幾次影片,一定要自己手動實現。很多面試可能會讓手寫。一次不行就看完原理後多實践幾次,直到能自己独立完成。
172172
- 每章講義後面都會有我設計的幾個小問題,最好能够回答上來。同時還有原始碼練習題,你可以挑戰下自己的掌握程度。
173-
- 最好按照顺序循序漸進,每章都會有铺垫和联系,後面的章節可能會使用到前面提到的數據結構
173+
- 最好按照順序循序漸進,每章都會有铺垫和联系,後面的章節可能會使用到前面提到的數據結構
174174
- 根據自己的基礎結合我列舉的教材和影片學習,第一次理解不了的可以反复多看幾次,多編寫原始碼練習到熟练為止
175175

176176
## 課程目標
@@ -228,7 +228,7 @@ alias watchtest='when-changed -v -r -1 -s ./ '
228228

229229
- 正常值功能測試
230230
- 邊界值(比如最大最小,最左最右值)
231-
- 异常值(比如 None,空值,非法值)
231+
- 異常值(比如 None,空值,非法值)
232232

233233
```
234234
def binary_search(array, target):
@@ -251,7 +251,7 @@ def test():
251251
如何設計測試用例:
252252
- 正常值功能測試
253253
- 邊界值(比如最大最小,最左最右值)
254-
- 异常值(比如 None,空值,非法值)
254+
- 異常值(比如 None,空值,非法值)
255255
"""
256256
# 正常值,包含有和無兩種結果
257257
assert binary_search([0, 1, 2, 3, 4, 5], 1) == 1
@@ -262,7 +262,7 @@ def test():
262262
assert binary_search([0, 1, 2, 3, 4, 5], 5) == 5
263263
assert binary_search([0], 0) == 0
264264
265-
# 异常值
265+
# 異常值
266266
assert binary_search([], 1) == -1
267267
```
268268

@@ -285,8 +285,8 @@ def test():
285285
[contributors](https://github.com/PegasusWang/python_data_structures_and_algorithms/graphs/contributors)
286286

287287
## 如何更新原始碼(寫给不熟悉 git 的同學)
288-
如果你直接 clone 的本项目的原始碼仓库,可以直接使用 `git pull origin master` 拉取更新。
289-
如果你先 fork 到了自己的仓库,然後 clone 到本地的是你自己的仓库,你可以編辑本地项目的 `.git/config`
288+
如果你直接 clone 的本项目的原始碼仓庫,可以直接使用 `git pull origin master` 拉取更新。
289+
如果你先 fork 到了自己的仓庫,然後 clone 到本地的是你自己的仓庫,你可以編辑本地项目的 `.git/config`
290290
增加如下配置:
291291

292292
```sh
@@ -319,7 +319,7 @@ pip install https://github.com/mitya57/python-markdown-math/archive/master.zip
319319
# 或者直接
320320
pip install -r requirements.txt
321321

322-
# 如果你 fork 了本项目,可以定期拉取主仓库的原始碼來获取更新,目前還在不断更新相關章節
322+
# 如果你 fork 了本项目,可以定期拉取主仓庫的原始碼來獲取更新,目前還在不断更新相關章節
323323
```
324324

325325
你可以 clone 本项目後在本地編寫和查看電子書:

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

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

55
程序 = 算法 + 數據結構
66

7-
算法(Algorithm):是指解题方案的准確而完整的描述,是一系列解決問題的清晰指令,算法代表着用系统的方法描述解決問題的策略機制。也就是說,能够對一定規範的輸入,在有限時間内获得所要求的輸出
7+
算法(Algorithm):是指解题方案的准確而完整的描述,是一系列解決問題的清晰指令,算法代表着用系统的方法描述解決問題的策略機制。也就是說,能够對一定規範的輸入,在有限時間内獲得所要求的輸出
88

99
數據結構(Data Structures):是計算機存儲和組織數據的一種方式,可以用來高效地處理數據。
1010

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
數組是最常用到的一種線性結構,其實 python 内置了一個 array 模塊,但是大部人甚至從來没用過它。
1111
Python 的 array 是記憶體連續、存儲的都是同一數據類型的結構,而且只能存數值和字符。
1212

13-
我建議你課下看下 array 的文档https://docs.python.org/2/library/array.html
13+
我建議你課下看下 array 的文件https://docs.python.org/2/library/array.html
1414

1515
你可能很少會使用到它(我推荐你用 numpy.array),我將在影片裡簡單介绍下它的使用和工作方式,最常用的還是接下來要說的 list,
1616
本章最後我們會用 list 來實現一個固定長度、並且支持所有 Python 數據類型的數組 Array.
1717

1818

1919
# 列表 list
20-
如果你學過 C++,list 其實和 C++ STL(標准模板库)中的 vector 很類似,它可能是你的 Python 學習中使用最頻繁的數據結構之一。
20+
如果你學過 C++,list 其實和 C++ STL(標準模板庫)中的 vector 很類似,它可能是你的 Python 學習中使用最頻繁的數據結構之一。
2121
這裡我們不再去自己實現 list,因為這是個 Python 提供的非常基础的數據類型,我會在影片中講解它的工作方式和記憶體分配策略,
2222
避免使用過程中碰到一些坑。當然如果你有毅力或者興趣的了解底层是如何實現的,可以看看 cpython 解释器的具體實現。
2323

docs/03_链表/linked_list.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ linked_list.remove(value) | O(n) |
4747

4848

4949
# 双鏈表
50-
上邊我們亲自實現了一個單鏈表,但是能看到很明显的問題,單鏈表雖然 append 是 O(1),但是它的 find 和 remove 都是 O(n)的,
50+
上邊我們親自實現了一個單鏈表,但是能看到很明显的問題,單鏈表雖然 append 是 O(1),但是它的 find 和 remove 都是 O(n)的,
5151
因為删除你也需要先查找,而單鏈表查找只有一個方式就是從頭找到尾,中間找到才退出。
5252
這裡我之前提到過如果要實現一個 lru 缓存(訪問時間最久的踢出),我們需要在一個鏈表裡能高效的删除元素,
5353
並把它追加到訪問表的最後一個位置,這個時候單鏈表就满足不了了,
54-
因為缓存在 dict 裡查找的時間是 O(1),你更新訪問顺序就 O(n)了,缓存就没了優势。
54+
因為缓存在 dict 裡查找的時間是 O(1),你更新訪問順序就 O(n)了,缓存就没了優势。
5555

5656
這裡就要使用到双鏈表了,相比單鏈表來說,每個節點既保存了指向下一個節點的指針,同時還保存了上一個節點的指針。
5757

@@ -86,7 +86,7 @@ cdll.tailnode() | O(1) |
8686
- 這裡單鏈表我没有實現 insert 方法,你能自己嘗試實現嗎? insert(value, new_value),我想在某個值之前插入一個值。你同樣需要先查找,所以這個步骤也不够高效。
8787
- 你能嘗試自己實現個 lru cache 嗎?需要使用到我們這裡提到的循環双端鏈表
8888
- 借助内置的 collections.OrderedDict,它有兩個方法 popitem 和 move_to_end,我們可以迅速實現一個 LRU cache。請你嘗試用 OrderedDict 來實現。
89-
- python 内置库的哪些數據結構使用到了本章講的鏈式結構
89+
- python 内置庫的哪些數據結構使用到了本章講的鏈式結構
9090

9191

9292
# 相關閱讀

docs/03_链表/lru_cache.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,19 @@ def f(n):
4343
問題來了,假如空間有限怎麼办,我們不可能一直向缓存塞東西,當缓存达到一定個數之後,我們需要一種策略踢出一些元素,
4444
用來给新的元素腾出空間。
4545
一般缓存失效策略有
46-
- LRU(Least-Recently-Used): 替換掉最近請求最少的對象,實際中使用最广。cpu缓存淘汰和虚拟記憶體效果好,web应用欠佳
46+
- LRU(Least-Recently-Used): 替換掉最近請求最少的對象,實際中使用最广。cpu缓存淘汰和虚拟記憶體效果好,web應用欠佳
4747
- LFU(Least-Frequently-Used): 缓存污染問題(一個先前流行的缓存對象會在缓存中驻留很長時間)
4848
- First in First out(FIFO)
4949
- Random Cache: 随機選一個删除
5050
5151
LRU 是常用的一個,比如 redis 就實現了這個策略,這裡我們來模擬實現一個。
52-
要想實現一個 LRU,我們需要一種方式能够记录訪問的顺序,並且每次訪問之後我們要把最新使用到的元素放到最後(表示最新訪問)。
52+
要想實現一個 LRU,我們需要一種方式能够记录訪問的順序,並且每次訪問之後我們要把最新使用到的元素放到最後(表示最新訪問)。
5353
當容量满了以後,我們踢出最早訪問的元素。假如用一個鏈表來表示的話:
5454
5555
[1] -> [2] -> [3]
5656
5757
假设最後面是最後訪問的,當訪問到一個元素以後,我們把它放到最後。當容量满了,我們踢出第一個元素就行了。
58-
一開始的想法可能是用一個鏈表來记录訪問顺序,但是單鏈表有個問題就是如果訪問了中間一個元素,我們需要拿掉它並且放到鏈表尾部。
58+
一開始的想法可能是用一個鏈表來记录訪問順序,但是單鏈表有個問題就是如果訪問了中間一個元素,我們需要拿掉它並且放到鏈表尾部。
5959
而單鏈表無法在O(1)的時間内删除一個節點(必须要先搜索到它),但是双端鏈表可以,因為一個節點记录了它的前後節點,
6060
只需要把要删除的節點的前後節點鏈接起來就行了。
6161
還有個問題是如何把删除後的節點放到鏈表尾部,如果是循環双端鏈表就可以啦,我們有個 root 節點鏈接了首位節點,
@@ -71,7 +71,7 @@ class LRUCache:
7171
def __init__(self, capacity=128):
7272
self.capacity = capacity
7373
# 借助 OrderedDict 我們可以快速實現一個 LRUCache,OrderedDict 内部其實也是使用循環双端鏈表實現的
74-
# OrderedDict 有兩個重要的函數用來實現 LRU,一個是 move_to_end,一個是 popitem,請自己看文档
74+
# OrderedDict 有兩個重要的函數用來實現 LRU,一個是 move_to_end,一個是 popitem,請自己看文件
7575
self.od = OrderedDict()
7676

7777
def get(self, key, default=None):

docs/04_队列/array_queue.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33

4-
# NOTE: 從 array_and_list 第一章拷贝的原始碼
4+
# NOTE: 從 array_and_list 第一章拷貝的原始碼
55
class Array(object):
66

77
def __init__(self, size=32):
@@ -59,7 +59,7 @@ def test_queue():
5959
for i in range(size):
6060
q.push(i)
6161

62-
with pytest.raises(FullError) as excinfo: # 我們來測試是否真的抛出了异常
62+
with pytest.raises(FullError) as excinfo: # 我們來測試是否真的抛出了異常
6363
q.push(size)
6464
assert 'full' in str(excinfo.value)
6565

docs/04_队列/queue.md

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

99
- 陣列。没错就是咱平常排隊,第一個來的第一個走
1010

11-
本章我們详细講講常用的陣列
11+
本章我們詳細講講常用的陣列
1212

1313
# 陣列 Queue
1414

@@ -32,7 +32,7 @@
3232
- 2.删除頭元素 LinkedList.popleft(),追加 append(element)。都可以满足
3333
- 3.哇欧,這兩個操作都是 O(1) 的,完美。
3434

35-
好, 就用 LinkedList 了,我們開始實現,具體看影片。這次實現我們還將演示自定義异常和測試异常
35+
好, 就用 LinkedList 了,我們開始實現,具體看影片。這次實現我們還將演示自定義異常和測試異常
3636

3737

3838
# 用數組實現陣列
@@ -79,7 +79,7 @@ for i in range(100):
7979
- remove(node) # O(1)
8080

8181
啊哈,似乎删除頭尾都可以啦,而且都是 O(1) 的,完美。
82-
交给你一個艰巨的任务,實現双端陣列 Deque() ADT。你可以参考前幾章的任何原始碼,挑战一下這個任务,别忘记寫單元測試呦。當然如果没想出來也没關系,後面我們實現堆疊的時候還會用到它,那裡我們會實現這個原始碼。
82+
交给你一個艰巨的任务,實現双端陣列 Deque() ADT。你可以参考前幾章的任何原始碼,挑戰一下這個任务,别忘记寫單元測試呦。當然如果没想出來也没關系,後面我們實現堆疊的時候還會用到它,那裡我們會實現這個原始碼。
8383

8484

8585
# 思考题

docs/04_队列/queue.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from collections import deque
44

5-
# NOTE:注意這裡是第三章 linked_list.py 裡的内容,為了使文件自包含,我直接拷贝過來的
5+
# NOTE:注意這裡是第三章 linked_list.py 裡的内容,為了使文件自包含,我直接拷貝過來的
66

77

88
class Node(object):
@@ -118,7 +118,7 @@ def clear(self):
118118

119119

120120
class EmptyError(Exception):
121-
"""自定義异常"""
121+
"""自定義異常"""
122122
pass
123123

124124

@@ -154,8 +154,8 @@ def test_queue():
154154
assert q.pop() == 2
155155

156156
import pytest # pip install pytest
157-
with pytest.raises(EmptyError) as excinfo: # 我們來測試是否真的抛出了异常
158-
q.pop() # 繼续調用會抛出异常
157+
with pytest.raises(EmptyError) as excinfo: # 我們來測試是否真的抛出了異常
158+
q.pop() # 繼续調用會抛出異常
159159
assert 'empty queue' == str(excinfo.value)
160160

161161

0 commit comments

Comments
 (0)