hash冲突解决

来源:互联网 发布:卡乐购系统域名 编辑:程序博客网 时间:2024/05/19 02:29

http://jpkc.xaau.edu.cn/sjjg/datastru/zxxx/seven%20lesson/743.html



开放地址法就是从发生冲突的那个单元开始,按照一定的次序,从哈希表中查找一个空闲的存储单元,把发生冲突的待插入元素存入到该单元中的一种处理冲突的方法。使用开放地址法,哈希表中的地址为d的空闲存储单元,不仅允许哈希地址为d的数据元素使用,也允许发生冲突的其他数据元素使用。即空闲存储单元不仅对同义词元素开放,也对非同义词元素开放,这就是开放地址法名称的来源。在使用开放地址法处理冲突的哈希表中,地址为d的单元存储的是同义词中的一个数据元素,还是非同义词中的一个数据元素,由谁先占用它决定。 
一个哈希表,如果是采用开放地址法来解决冲突,那么查找一个数据元素的过程就是:首先根据给定的关键字key,带入相应的哈希函数,计算出哈希地址d。然后比较d单元的数据元素的关键字是否为key。如果是,则查找成功;否则,按照和插入时处理冲突相同的次序依次比较,直到查找成功,或找到一个空的存储单元为止。而找到空的存储单元,意味着查找失败。 
开放地址法中,发生冲突时查找空闲存储单元常用的方法有线性探查法、平方探查法和双哈希函数探查法。 
    (1)线性探查法 
    线性探查法是开放法中处理冲突的一种最简单的探查方法,它从发生冲突的d单元开始,依次探查下一个单元,当到达表尾时,再从第一个单元开始探查,也就是把哈希表看作首尾相接的循环表,直到找到一个空闲的存储单元为止。这种方法的探查序列为: 
1
例7-3 关键字集为 {47,7,29,11,16,92,22,8,3},哈希表表长为11,哈希函数为Hash(key)=key % 11,用线性探查法处理冲突,建表如下:


0

1

2

3

4

5

6

7

8

9

10

11

22

 

47

92

16

3

7

29

8

 

47、7、11、16、92均是由哈希函数得到的没有冲突的哈希地址而直接存入的; 
Hash(29)=7,哈希地址上冲突,需寻找下一个空的哈希地址: 
由d1=(Hash(29)+1) % 11=8,哈希地址8为空,将29存入。另外,22、8同样在哈希地址上有冲突,也是由d1找到空的哈希地址的。 
而Hash(3)=3,哈希地址上冲突,由d1=(Hash(3)+1) % 11=4,仍然冲突;d2=(Hash(3)+2) % 11=5,仍然冲突;d3=(Hash(3)+3) % 11=6,找到空的哈希地址,存入。 
线性探查法可能使第i个哈希地址的同义词存入第i+1个哈希地址,这样本应存入第i+1个哈希地址的元素变成了第i+2个哈希地址的同义词。因此,可能出现很多元素在相邻的哈希地址上“堆积”起来,大大降低了查找效率。为此,可采用平方探查法,或双哈希函数探查法,以改善“堆积”问题。 
    (2)平方探查法 
平方探查法的探查序列为2,使用公式可表示为: 
3
    平方探查法时一种较好的处理冲突的方法,能够较好地避免堆积现象。它的缺点是不能探查到哈希表上所有的单元,但至少能探查到一半单元。例如当d=5,m=17时,则只能探查到下标依次是5、6、9、14、4、13、7、3、1的单元,而不能探查到剩余的单元。不过在实际应用中,能探查到一半单元就可以了。若探查到一半单元还找不到一个空闲的单元,表明此哈希表太满,应该重新建立。 
仍以上例用平方探查法处理冲突,建表如下:


0

1

2

3

4

5

6

7

8

9

10

11

22

 

47

92

16

3

7

29

8

 

(3)双哈希函数探查法 
    这种方法使用两个哈希函数Hash1(key)和Hash2(key),第一个哈希函数的作用和前面哈希函数的作用相同,而第二个哈希函数的值是作为探查序列的地址增量。双哈希函数探查法的探查序列可以用公式表示为: 
4
    以上三种方法,区别主要在于探查序列步长不同。对于线性探查法,探查序列的步长值固定是1,对于平方探查法,探查序列的步长值是探查次数i的两倍减1,对于双哈希函数探查法,探查序列的步长是同一关键字的另一哈希函数的值。

  1. 拉链法

    设哈希函数得到的哈希地址域在区间[0,m-1]上,以每个哈希地址作为一个指针,指向一个单链表链,即分配一个指针数组: 
Elemtype *eptr[m]; 
    建立m个空链表,由哈希函数对关键字转换后,映射到同一哈希地址i的同义词均加入到*eptr[i]指向的链表中。 
例7-4 关键字序列为{47,7,29,11,16,92,22,8,3,50,37,89,94,21},哈希函数为: 
Hash(key)=key % 11
    用拉链法处理冲突,建表如图7-8所示,向链表中插入元素均在表头进行。 
5
图7-8 拉链法处理冲突时的哈希表 
3.公共溢出区法 
    设哈希函数产生的哈希地址集为[0,m-1],则分配两个表: 
    一个基本表 Elemtype base_tbl[m];每个单元只能存放一个元素; 
    一个溢出表 Elemtype over_tbl[k];只要关键字对应的哈希地址在基本表上产生冲突,则所有这样的元素一律存入溢出表中。查找时,对给定值key通过哈希函数计算出哈希地址i,先与基本表的base_tbl[i]单元比较,若相等,查找成功;否则,再到溢出表中进行查找。


0 0
原创粉丝点击