“哈希表主体只承诺字典语义与负载参数,冲突策略应分层阅读:通用哈希给对固定键集的碰撞期望,Perfect Hashing针对静态集合换最坏常数查询,开放定址把键直接放入数组并依探测链,Cuck…”
两位置不变量 ​
两个来自合适通用哈希族的独立函数给键
Cuckoo 图刻画 ​
把两张表的槽作为二分图顶点,每个键作为连接两个候选槽的边。为每条边选择一个端点存放,且每顶点容量一;经典单槽模型可成功放置,当且仅当每个连通分量的边数不超过顶点数,即分量至多含一个环。树分量沿路径定向即可,双环分量必有某槽承担两键。
踢出路径例子 ​
新键
概率与装载边界 ​
在低于经典阈值、哈希足够随机时,插入期望摊还常数;接近阈值时复杂分量和长路径概率迅速增加。桶化 cuckoo、更多候选和 stash 改变阈值与查询位置数,须另写模型。查询的常数最坏界不含重建期间的并发语义;Las Vegas 版本通过重试保证结果正确,但运行时间随机。
Rehash 的摊还语义 ​
检测到环后,给当前全部键重新抽一对哈希函数并从空表构建;若仍失败继续重试。只要装载低于相应随机图阈值,单次全表构建成功概率有常数下界,所以重试次数期望常数,重建总成本可向自上次扩容以来的插入摊还。
这个结论要求失败时更换函数,而不是沿同一环从另一个起点继续踢。扩容也改变图顶点数和阈值。若系统要求每次插入最坏延迟,需要增量 rehash、stash 或 deamortization,并重新说明查询要检查哪些旧/新位置。
失败分量怎样被识别 ​
设候选槽为
实现可按以下顺序处理:
- 限制一次踢出的最大步数,并记录本轮访问状态;
- 超限后把新键和被踢出的键一起保留在临时区,不能丢失;
- 抽取新哈希函数,从空表重插全部键;
- 若仍遇坏分量则重试,达到负载阈值时先扩容。
查找只检查两个槽的最坏
参考资料
- Rasmus Pagh, Flemming Friche Rodler, Cuckoo Hashing, Journal of Algorithms, 2004.
- Michael Mitzenmacher, Some Open Questions Related to Cuckoo Hashing, ESA, 2009.