Skip to content

Latest commit

 

History

History
48 lines (34 loc) · 3.38 KB

File metadata and controls

48 lines (34 loc) · 3.38 KB

Robin Hood Hashing should be your default Hash Table implementation

TL;DR

Robin Hood哈希表通过公平性元素交换机制与方差控制,实现在高负载因子(如0.9)下保持高效,内存节省30%。采用线性探测、墓碑标记策略优化插入/删除性能,其查找通过空位判定与早停策略减少缓存缺失。测试显示较VS 2012 unordered_map快23-66%,适用于缓存友好及资源受限场景。

Summary

结构化总结:

  1. 核心优势:

    • 支持高负载因子(默认0.9,甚至0.95以上),且不影响性能,插入成本稍增但整体效率提升。
    • 不依赖链表或额外指针,结构为简单扁平数组,减少内存开销(节省约30%)和缓存缺失。
    • 插入、查找操作无需遍历链表,线性探测简单高效,性能表现优异,优于VS 2012的标准unordered_map。
  2. 性能提升关键:

    • 方差控制:通过减少探测次数的方差,优化缓存访问效率。在负载因子0.9时,平均探测方差仅0.98,而普通开放寻址法方差达16.2;负载0.99时,其方差为1.87,后者方差暴涨至194。
    • 公平性机制:插入时若发现已有元素的探测距离(存活时间)小于当前元素距离,则进行交换,实现“劫富济贫”。这使新元素获得更优的位置,使元素分布更均匀。
  3. 探测与交换逻辑:

    • 插入元素时从目标槽开始线性探测,计算自身当前探测步数dist
    • 当探测到已有元素的存活距离(其插入时的探测步数)小于dist时,进行交换(利用移动语义减少开销),继续探测直至找到空位。
    • 最大探测距离仍需记录,但通过较低方差,其值保持在小范围内(如负载0.9时约为6),降低查找失败的复杂度。
  4. 删除操作处理:

    • 不直接清空槽位,而是标记为“墓碑”(tombstone)。墓碑标记占1位,维护元素存活距离信息。
    • 插入时优先覆盖无用元素(如空位),仅在探测距离差距足够时覆盖“墓碑”,避免破坏哈希平衡。
  5. 查找优化:

    • 空位判定:若探测路径中遇到空位,说明目标元素不存在。
    • 早停策略:当探测步数超过当前元素存活距离时提前终止(利用插入时的交换规则保证逻辑正确),减少对缓存不命中的依赖。
  6. 实验数据:

    • 在插入10万英语单词并删除10%的测试中,Robin Hood哈希表比std::unordered_map快23%(插入)、66%(删除)、25%(查找),同时内存使用减少30%。
    • 最长探测序列增长极缓,即使负载接近饱和(如0.99),仍可通过有限次数探测判定元素存在性。
  7. 实现细节:

    • 存储元素的哈希值(如32位),用于快速比较与减少哈希计算开销。
    • 空槽标记为哈希值0,确保哈希函数不会返回此值。
    • 分离哈希值存储以提升缓存局部性,但可选择与键值共存以适应小型键值。
  8. 适用场景:

    • 现代CPU缓存优化场景下尤为适用,因其探测次数集中在缓存线范围内,减少内存带宽消耗。
    • 需要高效内存利用率的系统,如嵌入式或资源受限环境。