Skip to content

Commit 54b8b2f

Browse files
committed
1 parent f636089 commit 54b8b2f

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

docs/07_哈希表/hashtable.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def __iter__(self):
2929

3030
class Slot(object):
3131
"""定义一个 hash 表数组的槽(slot 这里指的就是数组的一个位置)
32-
注意,一个槽有三种状态,看你能否想明白。相比链接法解决冲突,二次探查法删除一个 key 的操作稍微复杂。
32+
注意,一个槽有三种状态,看你能否想明白。相比链接法解决冲突,探查法删除一个 key 的操作稍微复杂。
3333
1.从未使用 HashMap.UNUSED。此槽没有被使用和冲突过,查找时只要找到 UNUSED 就不用再继续探查了
3434
2.使用过但是 remove 了,此时是 HashMap.EMPTY,该探查点后边的元素仍然可能是有key的,需要继续查找
3535
3.槽正在使用 Slot 节点
@@ -65,23 +65,28 @@ def _find_key(self, key):
6565
因为使用的是二次探查的方式,假如有两个元素 A,B 冲突了,首先A hash 得到是 slot 下标5,A 放到了第5个槽,之后插入 B 因为冲突了,所以继续根据二次探查方式放到了 slot8。
6666
然后删除 A,槽 5 被置为 EMPTY。然后我去查找 B,第一次 hash 得到的是 槽5,但是这个时候我还是需要第二次计算 hash 才能找到 B。但是如果槽是 UNUSED 我就不用继续找了,我认为 B 就是不存在的元素。这个就是 UNUSED 和 EMPTY 的区别。
6767
"""
68-
index = self._hash(key)
68+
origin_index = index = self._hash(key) # origin_index 判断是否又走到了起点,如果查找一圈了都找不到则无此元素
6969
_len = len(self._table)
7070
while self._table[index] is not HashTable.UNUSED:
7171
if self._table[index] is HashTable.EMPTY: # 注意如果是 EMPTY,继续寻找下一个槽
72-
index = (index*5 + 1) % _len
72+
index = (index * 5 + 1) % _len
73+
if index == origin_index:
74+
break
7375
continue
74-
elif self._table[index].key == key:
76+
if self._table[index].key == key: # 找到了key
7577
return index
7678
else:
77-
index = (index*5 + 1) % _len
79+
index = (index * 5 + 1) % _len # 没有找到继续找下一个位置
80+
if index == origin_index:
81+
break
82+
7883
return None
7984

8085
def _find_slot_for_insert(self, key):
8186
index = self._hash(key)
8287
_len = len(self._table)
83-
while not self._slot_can_insert(index): # 直到找到一个可以用的槽
84-
index = (index*5 + 1) % _len
88+
while not self._slot_can_insert(index): # 直到找到一个可以用的槽
89+
index = (index * 5 + 1) % _len
8590
return index
8691

8792
def _slot_can_insert(self, index):

0 commit comments

Comments
 (0)