字典的實現方式
拉鍊法
i = hash(key) % solt
假設槽位有32個, 那麼得到的值很有可能會有衝突, i爲最後的該值處於哪個槽位。
將每個槽位做一個列表, 存值的時候append, 取值的時候遍歷。
如果算法足夠好的話, 就幾乎能實現近似O(1)了
實現:
In [58]: solts = []
...: solts_num = 32
...:
...: for _ in range(solts_num):
...: solts.append([])
...: def put(solts, key, value):
...: i = hash(key) % solts_num
...: solts[i].append((key, value))
...: def get(solts, key):
...: i = hash(key) % solts_num
...: for k, v in solts[i]:
...: if k == key:
...: return v
...: raise KeyError(k)
...:
In [59]: put(solts, 'r', 2)
In [60]: solts
Out[60]:
[[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[('r', 2)],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[]]
In [66]: put(solts, 'd', 2)
In [67]: get(solts, 'd')
Out[67]: 2
版本2:實現插入重複key的處理方式
In [69]: solts = []
...: solts_num = 32
...:
...: for _ in range(solts_num):
...: solts.append([])
...: def put(solts, key, value):
...: i = hash(key) % solts_num
...: p = -1
...: for p, (k, v) in enumerate(solts[i]):
...: if k == key:
...: break
...: else:
...: solts[i].append((key, value))
...: return
...: if p >=0:
...: solt[i][p] = (key, value)
...: def get(solts, key):
...: i = hash(key) % solts_num
...: for k, v in solts[i]:
...: if k == key:
...: return v
...: raise KeyError(k)
...:
版本3:類的實現
In [74]: class Dict:
...: def __init__(self, num):
...: self.__solts__ = []
...: self.num = num
...: for _ in range(num):
...: self.__solts__.append([])
...: def put(self, key, value):
...: i = hash(key) % self.num
...: for p, (k, v) in enumerate(self.__solts__[i]):
...: if k == key:
...: break
...: else:
...: self.__solts__[i].append((key, value))
...: return
...: self.__solts__[i][p] = (key, value)
...: def get(self, key):
...: i = hash(key) % self.num
...: for k, v in self.__solts__[i]:
...: if k == key:
...: return v
...: raise KeyError(key)
...:
In [75]: d = Dict(32)
In [76]: d.put('r', 2)
In [77]: d.put('d', 2)
In [78]: d.get('r')
Out[78]: 2
版本4:類的實現, 添加keys方法實現
In [79]: class Dict:
...: def __init__(self, num):
...: self.__solts__ = []
...: self.num = num
...: for _ in range(num):
...: self.__solts__.append([])
...: def put(self, key, value):
...: i = hash(key) % self.num
...: for p, (k, v) in enumerate(self.__solts__[i]):
...: if k == key:
...: break
...: else:
...: self.__solts__[i].append((key, value))
...: return
...: self.__solts__[i][p] = (key, value)
...: def get(self, key):
...: i = hash(key) % self.num
...: for k, v in self.__solts__[i]:
...: if k == key:
...: return v
...: raise KeyError(k)
...: def keys(self):
...: ret = []
...: for solt in self.__solts__:
...: for k, _ in solt:
...: ret.append(k)
...: return ret
...:
In [80]: d = Dict(32)
In [81]: d.put('r', 2)
In [82]: d.put('d', 2)
In [83]: d.keys()
Out[83]: ['d', 'r']
開地址法
i = hash(key) % solt 可以用相同的算法來做
假設槽位有32個, 那麼得到的值很有可能會有衝突, i爲最後的該值處於哪個槽位。
不同的是, 值衝突後的處理方法不同。
i = fn(key, i) # 如果被佔用, 就用算法去找下一個槽。如果槽還是被佔用, 就會去找下一個槽。
取值的時候, 用函數一個一個找下去。
集合在底層的實現, 就是一個忽略了value的字典