Skip to content

Commit d9112e7

Browse files
committed
2 parents 6b50e4d + 18a6409 commit d9112e7

File tree

5 files changed

+41
-14
lines changed

5 files changed

+41
-14
lines changed

.github/FUNDING.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# These are supported funding model platforms
2+
3+
github: [PegasusWang]
4+
custom: ["https://www.paypal.me/pegasuswang"]

163_course.png

298 KB
Loading

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
- 网上很多视频教程不够循序渐进,不成系统
2828

2929
## 作者简介
30-
曾就职于[知乎](https://www.zhihu.com/people/pegasus-wang/activities)任后端工程师,多年 Python 开发经验。
30+
曾就职于[知乎](https://www.zhihu.com/people/pegasus-wang/activities)现腾讯后端工程师,多年 Python 开发经验。
3131

3232
知乎专栏:
3333

@@ -301,9 +301,9 @@ def test():
301301
如果读者关于代码、视频、讲义有任何疑问,欢迎一起讨论
302302
请注意以下几点:
303303

304-
- 优先在网易云课堂的讨论区提问,方便别的同学浏览。如果未购买视频,也可以直接在 github 里提出 issue,笔者有空会给大家解答和讨论。
305-
- 描述尽量具体,视频或者代码哪一部分有问题?请尽量把涉及章节和代码贴出来,方便定位问题。
304+
- 描述尽量具体,视频或者代码哪一部分有问题(可以具体到文档或者代码行数)?请尽量把涉及章节和代码贴出来,方便定位问题。
306305
- 如果涉及到代码,提问时请保持代码的格式
306+
- 如果直接提了代码bug,最好有相关测试用例展示失败 test case,方便复现问题
307307

308308

309309
## 本电子书制作和写作方式
@@ -331,4 +331,4 @@ mkdocs gh-deploy # 部署到自己的 github pages
331331

332332
扫码加入课程:
333333

334-
![扫码加入课程返现30%](https://camo.githubusercontent.com/a217604a83d60fdc610ba91e5c771664a4645a79/687474703a2f2f376b747574792e636f6d312e7a302e676c622e636c6f7564646e2e636f6d2f53637265656e25323053686f74253230323031382d30362d3032253230617425323032302e33372e34362e706e67)
334+
![扫码加入课程](./163_course.png)

docs/03_链表/linked_list.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ def remove(self, value): # O(n)
7777
if curnode.value == value:
7878
prevnode.next = curnode.next
7979
if curnode is self.tailnode: # NOTE: 注意更新 tailnode
80-
self.tailnode = prevnode
80+
if prevnode is self.root:
81+
self.tailnode = None
82+
else:
83+
self.tailnode = prevnode
8184
del curnode
8285
self.length -= 1
8386
return 1 # 表明删除成功
@@ -185,6 +188,13 @@ def test_linked_list_remove():
185188
ll.remove(7)
186189
print(list(ll))
187190

191+
def test_single_node():
192+
# https://github.com/PegasusWang/python_data_structures_and_algorithms/pull/21
193+
ll = LinkedList()
194+
ll.append(0)
195+
ll.remove(0)
196+
ll.appendleft(1)
197+
assert list(ll) == [1]
188198

189199
def test_linked_list_reverse():
190200
ll = LinkedList()
@@ -203,6 +213,7 @@ def test_linked_list_append():
203213

204214

205215
if __name__ == '__main__':
216+
test_single_node()
206217
test_linked_list()
207218
test_linked_list_append()
208219
test_linked_list_reverse()

docs/07_哈希表/hashtable.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ def __iter__(self):
2828

2929

3030
class Slot(object):
31-
"""定义一个 hash 表 数组的槽
32-
注意,一个槽有三种状态,看你能否想明白。相比链接法解决冲突,二次探查法删除一个 key 的操作稍微复杂。
31+
"""定义一个 hash 表数组的槽(slot 这里指的就是数组的一个位置)
32+
hash table 就是一个 数组,每个数组的元素(也叫slot槽)是一个对象,对象包含两个属性 key 和 value。
33+
34+
注意,一个槽有三种状态,看你能否想明白。相比链接法解决冲突,探查法删除一个 key 的操作稍微复杂。
3335
1.从未使用 HashMap.UNUSED。此槽没有被使用和冲突过,查找时只要找到 UNUSED 就不用再继续探查了
3436
2.使用过但是 remove 了,此时是 HashMap.EMPTY,该探查点后边的元素仍然可能是有key的,需要继续查找
3537
3.槽正在使用 Slot 节点
@@ -60,23 +62,33 @@ def _hash(self, key):
6062
return abs(hash(key)) % len(self._table)
6163

6264
def _find_key(self, key):
63-
index = self._hash(key)
65+
"""
66+
解释一个 slot 为 UNUSED 和 EMPTY 的区别
67+
因为使用的是二次探查的方式,假如有两个元素 A,B 冲突了,首先A hash 得到是 slot 下标5,A 放到了第5个槽,之后插入 B 因为冲突了,所以继续根据二次探查方式放到了 slot8。
68+
然后删除 A,槽 5 被置为 EMPTY。然后我去查找 B,第一次 hash 得到的是 槽5,但是这个时候我还是需要第二次计算 hash 才能找到 B。但是如果槽是 UNUSED 我就不用继续找了,我认为 B 就是不存在的元素。这个就是 UNUSED 和 EMPTY 的区别。
69+
"""
70+
origin_index = index = self._hash(key) # origin_index 判断是否又走到了起点,如果查找一圈了都找不到则无此元素
6471
_len = len(self._table)
6572
while self._table[index] is not HashTable.UNUSED:
66-
if self._table[index] is HashTable.EMPTY:
67-
index = (index*5 + 1) % _len
73+
if self._table[index] is HashTable.EMPTY: # 注意如果是 EMPTY,继续寻找下一个槽
74+
index = (index * 5 + 1) % _len
75+
if index == origin_index:
76+
break
6877
continue
69-
elif self._table[index].key == key:
78+
if self._table[index].key == key: # 找到了key
7079
return index
7180
else:
72-
index = (index*5 + 1) % _len
81+
index = (index * 5 + 1) % _len # 没有找到继续找下一个位置
82+
if index == origin_index:
83+
break
84+
7385
return None
7486

7587
def _find_slot_for_insert(self, key):
7688
index = self._hash(key)
7789
_len = len(self._table)
78-
while not self._slot_can_insert(index):
79-
index = (index*5 + 1) % _len
90+
while not self._slot_can_insert(index): # 直到找到一个可以用的槽
91+
index = (index * 5 + 1) % _len
8092
return index
8193

8294
def _slot_can_insert(self, index):

0 commit comments

Comments
 (0)