哈希表(Hashtable)
依然从我们学习自问三部曲开始,什么是哈希表?哈希表有什么用?哈希表怎么用?
从百科上我们可以得知散列表(Hashtable)也被称为哈希表,它是根据关键码值<Key value>而进行直接访问的数据结构。它通过把关键码值映射到表中的一个位置来访问记录,以加快查找熟读。这个映射函数被称为哈希函数,存储记录的数组被称为散列表
那么既然说能加快查找速度,那么久不得不拿数组与链表进行比较了,数组你要查找一个元素得知道数组的下标,而链表却需要从头开始遍历,直到找到我们所需要的元素为止,这耗费大量的时间。
哈希表是怎么提高查找速度的
我们希望输入一个数的值就可以找到该数所在的位置
哈希函数构造方法
一、关键词为数字
1、直接地址法
公式:index = a*key+b
package test;
public class collectiontdemo {
public static int func(int i){
return (i-3000)/2;
}
public static void main(String []args){
int index;
int []arr = new int[1000];
//3000至3450之间的偶数
for(int i=3000;i<3450;i+=2){
index = func(i);
arr[index] = i;
}
index = func(3200);
System.out.println(index);
System.out.println(arr[index]);
}
}

2、除留余数法
公式:index = key%p
p为表的大小
package test; //将数组arr2中的九个元素进行取模,然后随机存到数组arr中 public class collectiontdemo { public static int func2(int key,int p){ return key%p; } public static void main(String []args){ int index; int p = 9; int []arr = new int[30]; int arr2[] = {999,111,0,256,333,777,9,2546,1024}; for(int i=0;i<arr2.length;i++){ index = func2(arr2[i],p); arr[index] = i; } for(int i=0;i<arr2.length;i++){ System.out.println(arr[i]); } } }
3、数字分析法
比如一个数组存了很多的电话号码,这些号码长度都为11,我们直接取值不太方便,如果我们能够以号码后四位作为判断标准,那么查找起来也比较方便
package test;
public class collectiontdemo {
public static int func3(char []value){
char a =value[1];
char b = value[3];
char c = value[4];
char d = value[2];
return (int)a*100+(int)b*10+(int)c;
}
public static void main(String []args){
String [] arr = new String [30];
int p =29;
int index;
String arr2[]={"15764914325","13846478246","13756445236","18734628132",
"13276482132"};
for(int i=0;i<arr2.length;i++){
char []arr1 = arr2[i].toCharArray();
index = func3(arr1)%p;
arr[index] =arr2[i];
}
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
输出结果

二、关键字为字符串
1、ASCLL码加和法
把每个字符的ASCLL码进行相加,进而得到key值
这种方法很大概率会导致哈希冲突
2、前三个字符移位法
index =(key[0])*27+key[1]*27+key[2])mod TableSize
仍会造成冲突且会造成空间浪费
3、移位法
把所有的字母都进行移位,然后得到key(32进制)
三、哈希冲突解决办法
不同的树在通过哈希函数运算后得到的index相等,就把它们放入了相同的地址,导致数据被覆盖。哈希冲突无法避免,当数据很大而储存空间较小的时候,无论多么完美的哈希函数与方法都会存在哈希冲突,我们可以通过优化哈希函数来降低冲突的概率。
1、开放地址法
当冲突发生时,用某种探测算法在散列表中寻找下一个散列表空的地址,只要列表足够大,总会找到。按照探测序列的方法,一般将开放地址法区分为线性探查法、二次探查法、双重散列法等。
我们用除留余数法将26、35、36记录插入表中,取模为8,然后再将18记录插入表中,发现取模后地址不为空,接下来就介绍这三种方法。

(1)线性探测法
index = a*index +i (i为递增的整数)
当2位置被占领我们就探查3位置,直到探查到5位置为空为止,当数据插入。容易出现越界,即探测完最后一个的时候全部满了,而没探测到前面却为空。
(2)二次探测法
index = a*index +i(i为1^2 , -1^2 , 2^2, -2^2 , 3^2 , -3^2……q^2, -q^2)
缺点是无法探测整个散列空间。
(3)连地址法
将所有的哈希地址相同的记录,都连接到链表当中。当有新的元素进来造成哈希冲突时,在冲突的地址链表后面加。

浙公网安备 33010602011771号