前言

散列(hashing)中,元素储存在一个散列表(hash table)内,它们在散列表的位置由散列函数(hashing function)确定, 每个位置可以称为(bucket)或者单元(cell).

散列函数

java.lang.Object中定义了public native int hashCode()方法,根据对象的内存地址返回了一个整数值,所有的java对象都可以被散列. 从Object派生而来的类通常会重写hashcode方法,以提供自己的hashcode版本.

最为典型的就是java.lang.String的hashcode实现
/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
* using {@code int} arithmetic, where {@code s[i]} is the
* <i>i</i>th character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return  a hash code value for this object.
*/
public int hashCode() {
   int h = hash;
   if (h == 0 && value.length > 0) {
       char val[] = value;

       for (int i = 0; i < value.length; i++) {
           h = 31 * h + val[i];
       }
       hash = h;
   }
   return h;
} 

参考注释,hash计算公式可以计为s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],  
n为字符串长度,s[]即为String源码中其内部维护的char类型的数组val[],  
推导如下:如果字符串长度 n = 3
i = 0 -> h = 31 * 0 + val[0] = val[0];
i = 1 -> h = 31 * (31 * 0 + val[0]) + val[1] =  31 * val[0] + val[1];
i = 2 -> h = 31 * (31 * (31 * 0 + val[0]) + val[1]) + val[2] = 31^2 * val[0] +31 * val[1] + val[2];

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

如有兴趣,请参考String hashCode()为何选用31作为乘子

直接寻址法

以数据元素关键字本身或它的线性函数作为它的hash地址,即Hk = k 或者 Hk = a*k+b(a,b为常数)
例1: 统计XX市年龄分布表,记录从1岁到110岁的人口数目,以年龄为关键字,hash函数取关键字本身.

地址 A1 A2 …… A100 …… A109 A110
年龄 1 2 …… 100 …… 109 110
人数 200 500 …… 30 …… 1 0

当要查询某一年龄对应的人数,直接查询对应的地址.如需查找100岁的人,读出100项的值.

实际应用当中,关键字很少连续,此方法生成的hash表可能造成空间的大量浪费
适用范围 地址集合大小==关键字集合大小

折叠法(folding method)

关键字被分割成多个部分,然后再组合或叠加到一起以创建散列表的索引.
实现方式: 将关键字按照所需的索引长度切分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位). 平移折叠法: 将分割后的每一部分的最低位对齐相加 边界折叠法: 从一端向另一端沿分割界来回折叠,然后对齐相加

适用范围 关键字位数较多,而且关键字中每一位上数字分布大致均匀

余数法

平方取中法

基数转换法

数字分析法

长度相关法

完美散列函数

散列冲突

两个元素或者关键字映射到散列表相同的位置的情况称为散列冲突

开放地址法

链地址法

上次更新: 2019-6-24 19:17:56