目录
哈希表:通过关键码来映射到值的一个数据结构;
哈希函数:键与值映射的一个映射关系;
哈希函数的构建:
常用方法:
1、直接寻址法:f(x) = kx+b (k、b都是常数) ,一旦确定了哈希函数,那么添加、获取元素都需要通过这个哈希函数;
2、除留余数法:f(x) = x%k (k是常数,k <= m (m为存储位置长度)) ;
其他几种方法:
方法名 | 说明 | 适合情况 |
---|---|---|
直接寻址法 | f(key) = key 或者 f(key) = a*key + b | 事先知道关键字的分布情况,查找表较小且连续 |
数字分析法 | 根据实际问题自己创造一个能将关键字散列表的各位置的散列函数 | 事先知道关键字的分布情况且关键字的若干位分布较均匀 |
平方取中法 | 先把关键字平方,然后取得到的结果的中间几位当哈希值 | 不知道关键字的分布,而位数又不是很大的情况 |
折叠法 | 把关键字分成较小的几组数据,求和,取得到结果的后几位当哈希值 | 不知道关键字的分布,且关键字位数较多情况 |
除留余数法 | f(key) = key%n ( n≤m )m为表长(容量),n 为不大于 m 的素数,或是不含 20 以下的质因子 | 一般都可以,所以是最常用的方法 |
随机数法 | f(key) = random(key) | 关键字长度不等的时候 |
哈希冲突:由于哈希函数构造不当,通过同一个哈希函数把两个不同的数哈希到了同一个位置;m != n ---->f(m) = f(n);哈希冲突无法避免,但可以减少(改变合适的哈希函数还是有可能发生哈希冲突,但冲突的数据会大大减少)。
解决哈希冲突:
常用方法:
1、链地址法:数组+链表(散列表)
2、探测法:① 线性探测:p(i) = i+c ②非线性探测:p(i) = i+random();
其他几种方法:
方法名 | 说明 | 注解 |
---|---|---|
开放地址法 | 一旦发生了冲突,就去寻找下一个地址,只要散列表足够大,空的地址总能够找到,找到则记录存入 | 找地址的方法有:线性探测法、二次探测法、随机探测法 |
再散列函数法 | 发生散列地址冲突时,换一个散列地址计算,相信总会有一个函数是可以解决冲突的 | 这种方法可以使关键字不产生聚集,但增加了计算时间 |
链地址法 | 数组+链表 | 这种方法绝不会出现找不到地址的情况,但是查找时要遍历链表 |
公共溢出区法 | 就是把冲突的关键字放在一个新表中 | 这个方法的查找性还是比较高的 |