哈希表动画演示

算个下标直接落桶,撞上了挂链子,太挤就扩容重排。

键盘:← → 单步 ·空格 播放/暂停 · R 重置 ·Home/End 到两端

哈希表把查找压成一次算术:对 key 算一个整数,再对桶的数量取模,直接落到那一格。理想情况下元素被均匀撒开,每次操作只看一个桶。这一页自己实现了一个 djb2 变体的小哈希,每一步都把 h(key) 的原值和取模结果写出来,落桶不是玄学,是可见的除法余数。

现实是余数会撞。冲突最常见的处理是挂链:同一个桶的元素串成一条链,查找时先进桶、再在链上逐个比。于是真实代价由最长链决定,而不是由桶数决定。为了压住最长链,引入负载因子(元素数除以桶数),它超过阈值就把桶数组变大后整体重排——阈值常取 0.75,再高冲突概率上升,再低就浪费内存和更频繁的搬迁。

哈希表演示怎么用

  • 看算式那一行:表格下方常驻五个格子:当前 key、它的哈希值、桶数、取模后的落桶、链上位置。每次插入查找都同步刷新,不用自己算。
  • 两套 key 方案:默认那套在旧表里就撞链,另一套先分散、扩容后才集中,正好对照出 rehash 会把挤在一起的 key 分开。选自定义可以在数据栏填一串短词。
  • 跟住扩容段:负载因子超阈值时,桶数组先变长,旧 key 按原行号挂着,再逐个摘下来用新容量重算桶号放回,一摘一放各一步,能看到「从第 3 行掉到第 0 行」。
  • 链放不下怎么办:一个桶最多画三个链上位置,超出的不丢数据,而是在最后一格标注还剩几个,退化过程如实显示。

常见问题

负载因子为什么常见取 0.75 而不是 1?

取 1 意味着装满才扩,此时冲突概率迅速抬头,平均链长变久;取太低则桶数翻倍得快、内存浪费明显,还频繁触发整体重排。0.75 是两者之间一个折中的经验值,很多实现就固定在这附近。

桶数为什么偏爱质数?

如果哈希值有某种周期(比如低位都是 0),桶数是 2 的幂时取模只看那几位,元素会扎堆;质数取模会把整串位都参与进来,分布更散。用 2 的幂的实现则要靠扰动函数把高位混下来。

查找失败为什么比命中更贵?

命中通常在链的前几个就返回,失败必须一路走到链尾的 ∅ 才能确定没有。桶越挤、链越长,这个差别越明显,这也是空查找最能暴露退化的一处。

扩容 rehash 期间会不会丢数据?

不会,但会慢:整体重排要把每个元素用新容量重算一次桶号,代价与元素数成正比,所以它是摊在很多次操作上的,不是每次插入都发生。

演示编号 B05无需安装,手机端同样可用按 Ctrl + K 搜工具与演示

顺手能用上的工具