HASH 散列的一些概念
0.散列表期望以常数平均时间实现查找与添加,但需注意散列函数的选取与装填因子等细节才能达到性能要求
1.散列函数(hash function )即关键字到表中单元的映射,key->tablePlace ,理想情况下,应是一 一映射。
2.冲突(collision)即不同的关键字散列到同一单元的情况。因为关键字基本上是无限的,而散列表有限,故冲突一般无法避免。
3.解决冲突的方法中最简单最常见的两类:分离链接法,开放定址法
4.装填因子(load factor),即元素个数与散列表大小的比值上限(不超过)。在java的hashmap中 为0.75 ,超过此值时将扩容
5.探测散列表,一种使用开放定址法解决冲突的表,他需要两个函数,一个是散列函数 h,一个是探测函数 f
一般的公式是 Indexi(x) = (h(x)+f(i))%size,f是冲突次数的函数。f(0)=0,即无冲突时只使用散列函数
探测散列表无法执行普通的删除,因为那个被删除的位置可能引起过冲突,如果将该位置元素删掉,那么因为冲突而被放到其他位置的那个元素也会被认为被删掉了
(a,b均散列到下标 3 处,a先来于是放进去了,b则探测到其他位置放进去了,若直接将3处的a删掉,则get(b)时,将发现3处是空的,则会以为没有b)
可用懒删除,即标记元素是否被删除。这样我们知道被删的是a而非b。
6.线性探测法,即f(i)=ai+b 一般的 f(i) = i;这容易导致一次聚集
7.平方探测法,即f(i)=i2 ,不会导致一次聚集,但有可能导致探测位置无法遍及整个哈希表,例如长度为16的表,首次hash到 3 后续hash始终在 4,7,12,3这几个位置,一旦这几个填满,即使其余都是空的,hash到3处的冲突就会发生无法解决的情况。解决方式是使长度为素数,且装填因子小于0.5。
8.双散列探测法,即f(i)=h2(x)*i ,对于第二个hash函数的选取是比较有技术含量的,
9.再散列,即重新构建一个散列表(至少是现有表的两倍大)。一般触发再散列的条件可以为1(表的一半位置填满)2(插入失败)3(装填因子达到某个预定值);较好的策略是第3种(装填因子需选取得当)。
10.布谷鸟散列,即用多个hash函数,使得一个关键字有多个可放置的位置(这多个位置可以在同一张表里,也可以是多个表;),当其中有位置为空时将之放入,当全都不为空时,随意选一个位置放入, 并对该位置的原关键字进行插入操作。
注意,这种占据另外关键字的位置并让其重新插入的操作可能造成循环,故需对这种占据其他关键字位置的行为设置上限,达到上限仍未完成插入则需扩表
装填因子需低于0.5才能显著降低循环发生的概率,当然合适的散列函数也很重要
11.跳房子散列,一种改造的线性探测法,要求探测的最大深度为一给定值M,当关键字被散列到位置P时,若P有元素则考察下一个,但最多考察到(P+M-1)%size的位置。若均被占据,则继续考察直到一个空位置Q,并尝试将P到空位Q之间的某些元素往空位上推,以求在P到(P+M-1)%size之间得到空位。这种散列方式需要一个与散列表等大的数组记录当前散列值的所有允许位置的合理占用情况(比如100100表示当前位置以及当前位置+3处的位置被合理占用,合理占用即指关键字可以在此处)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)