一、字典的实现
dic 可以使用list来实现
i(索引) = hash(key) % solt(槽位数)
此时i重复了怎么办(hash冲突)?
1、拉链法
每个槽位上拉一个List,就是拉链法
In [6]: solts = [] # 初始化一个list In [7]: solts_num = 32 # 假设32个槽位 In [8]: for _ in range(solts_num): ...: solts.append([]) ...: In [9]: solts # 每个槽位上都是一个list Out[9]: [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] ## 定义dict的put方法 In [10]: def put(solts, key, value): ...: i = hash(key) % solts_num ...: solts[i].append((key, value)) ...: ## 定义dict的get方法 In [12]: def get(solts, key): ...: i = hash(key) % solts_num ...: for k, v in solts[i]: ...: if k == key: ...: return v ...: raise KeyError(key) ...: ## 测试 In [23]: put(solts, 'a', 1) In [24]: solts Out[24]: [[('a', 1)], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] In [25]: put(solts, 'b', 2) In [26]: put(solts, 'f', 9) In [27]: solts Out[27]: [[('a', 1)], [], [], [], [], [], [], [], [], [], [], [], [('f', 9)], [], [('b', 2)], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] In [28]: get(solts, 'b') Out[28]: 2 In [29]: get(solts, 'f') Out[29]: 9 In [107]: get(solts, 'x') --------------------------------------------------------------------------- KeyError Traceback (most recent call last)in () ----> 1 get(solts, 'x') in get(solts, key) 4 if k == key: 5 return v ----> 6 raise KeyError(key) 7 KeyError: 'x'
此时put一个已存在的key时:
In [33]: put(solts, 'a', 11) In [34]: solts Out[34]: [[('a', 1), ('a', 11)], [], [], [], [], [], [], [], [], [], [], [], [('f', 9)], [], [('b', 2)], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] In [35]: get(solts, 'a') Out[35]: 1
重新定put方法:
In [87]: def put(solts, key, value): ...: i = hash(key) % solts_num ...: for p, (k, v) in enumerate(solts[i]): ...: if k == key: ...: solts[i][p] = (key, value) ...: else: ...: solts[i].append((key, value)) In [89]: solts Out[89]: [] In [90]: for _ in range(solts_num): ...: solts.append([]) ...: In [92]: put(solts, 'a', 1) In [94]: put(solts, 'b', 2) In [95]: put(solts, 'f', 8) In [96]: solts Out[96]: [[('a', 1)], [], [], [], [], [], [], [], [], [], [], [], [('f', 8)], [], [('b', 2)], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] In [101]: get(solts, 'b') Out[101]: 2 In [102]: get(solts, 'f') Out[102]: 8 In [103]: get(solts, 'a') Out[103]: 11 In [104]: put(solts, 'b', 22) In [105]: get(solts, 'b') Out[105]: 22 In [106]: solts Out[106]: [[('a', 11), ('a', 11)], [], [], [], [], [], [], [], [], [], [], [], [('f', 8)], [], [('b', 22), ('b', 22)], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] In [107]: get(solts, 'x') --------------------------------------------------------------------------- KeyError Traceback (most recent call last)in () ----> 1 get(solts, 'x') in get(solts, key) 4 if k == key: 5 return v ----> 6 raise KeyError(key) 7 KeyError: 'x'
set在底层的实现就是一个忽略了value的dict
2、开地址法
使用某个算法重新计算i,就交开地址法
常用,效率更高,
i = fn(key, i)
待后续学习