# 哈希函数
好的哈希函数应该尽可能让计算的过程变得简单, 应该可以快速计算出结果。
好的哈希函数应该具备哪些优点呢?
快速的计算
哈希表的优势在于效率,所以快速获取对应的 hashCode 非常重要。
均匀的分布
哈希表中,无论是链地址法还是开放地址法,当多个元素映射到同一个位置的时候,都会影响效率。
所以优秀的哈希函数应该尽可能将元素映射到不同的位置,让元素在哈希表中均匀分布。
因此,我们需要在使用常量的地方,尽量的使用质数
质数的使用
哈希表的长度
N次幂的底数(之前使用的是27)
为什么使用质数可以是哈希表分布均匀?
- 哈希表的长度使用质数:
这个在链地址法中事实上重要性不是特别明显, 明显的是在开放地址法中的再哈希法中。
- 再哈希法中质数的重要性:
假设表的容量不是质数, 例如: 表长为15(下标值0~14)
有一个特定关键字映射到0, 步长为5。探测序列是多少呢?
0 - 5 - 10 - 0 - 5 - 10, 依次类推, 循环下去。
算法只尝试着三个单元, 如果这三个单元已经有了数据, 那么会一直循环下去, 直到程序崩溃。
如果容量是一个质数, 比如13。探测序列是多少呢?
0 - 5 - 10 - 2 - 7 - 12 - 4 - 9 - 1 - 6 - 11 - 3 一直这样下去。
不仅不会产生循环, 而且可以让数据在哈希表中更加均匀的分布。
# 哈希函数实现
// 哈希函数
// 1.将字符串转成比较大的数字hashCode
// 2.将大的数字hashCode压缩到数组范围之内
function hashFunc (str, size = 7) {
// 一个质数
const PRIME = 31;
// 1.定义hasCode变量
let hashCode = 0
// 2.霍纳算法计算 hashCode 的值
for (let i = 0; i < str.length; i++) {
hashCode = PRIME * hashCode + str.charCodeAt(i)
}
// 3.取余操作
let index = hashCode % size
return index
}
console.log(hashFunc('abc', 7)) // 4
console.log(hashFunc('add', 7)) // 2
console.log(hashFunc('aio', 7)) // 2
console.log(hashFunc('acasd', 7)) // 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21