概念:在记录的存储位置和它的关键字之间建立一个确定对应关系f,使得每个关键字key对应一个存储位置f(key)。
这种对应关系称之为散列函数,又称哈希函数。散列技术将记录存储于一块连续存储空间中,这个连续存储空间 称之为散列表或哈希表。
常用构造方法——直接定址法、数字分析法、平方取中法、折叠法、残留余数法。
主要分析:残留余数法
f(key) = key mod p (p <= m)
mod是取模(取余)
p一般是取比m小,但最接近于m的质数(质数:能被自身或1除的数,如1、3、5、7...)
ex:对以下12个关键字以表长12取模分别放入相应的位置。
下标 0 1 2 3 4 5 6 7 8 9 10 11
关键字 12 25 38 15 16 29 78 67 56 21 22 47
当然,通常情况会有冲突
如18、30、42,这些数最后都会与序号为6的冲突,18mod12=6 30mod12=6 42mod12=6
常用解决冲突的方法——开放定址法、再散列函数法、链地址法、公共溢出区法
主要分析:开放定址法(线性探测法)
fi(key) = ( f(key) + di ) mod m (di = 1,2,3,...,m-1)
如果遇到冲突,就继续将散列值与di相加,接着残留余数法散列。
二次探测法
fi(key) = ( f(key) + q ) mod m (di = 1^2,-1^2,2^2,-2^2,...,q^2,-q^2,q<=m/2)
此方法是为了不让散列值集中在某区域。
随机探测法
fi(key) = ( f(key) + di ) mod m (di为随机序列)
package 散列表;
import java.util.Random;
public class HashProcess {
public static void main(String[] args) {
int[] arr = new int[10];
int[] hashTable = new int[arr.length*2+1];
Random random = new Random();
for(int i=0 ; i<arr.length ; i++){
arr[i] = random.nextInt(10)%10+10;
}
for(int a : arr){
InsertHash(hashTable,a);
System.out.print(a + " ");
}
System.out.println(SearchHash(arr[6],hashTable.length,hashTable));
}
private static boolean SearchHash(int a,int len,int[] ht) {
int addr = Hash(a,len);
while(ht[addr] != a){
addr = (addr+1)%len;
if(ht[addr] == 0 || addr == Hash(a,len)){
return false;
}
}
return true;
}
private static void InsertHash(int[] hashTable, int a) {
int len = hashTable.length;
int addr = Hash(a,len);
while(hashTable[addr] != 0){
addr = (addr+1)%len;
}
hashTable[addr] = a;
}
private static int Hash(int a,int len) {
return a%len;
}
}