数据结构与算法18—哈希表(散列表) (2)

开放定址法(开地址法)、 链地址法(拉链法)、 再哈希法(双哈希函数法)、 建立一个公共溢出区,而最常用的就是开发定址法链地址法

1、开放定址法

如果两个数据元素的哈希值相同,则在哈希表中为后插入的数据元素另外选择一个表项。当程序查找哈希表时,如果没有在第一个对应的哈希表项中找到符合查找要求的数据元素,程序就会继续往后查找,直到找到一个符合查找要求的数据元素,或者遇到一个空的表项。线性探测带来的最大问题就是冲突的堆积,你把别人预定的坑占了,别人也就要像你一样去找坑。改进的办法有二次方探测法和随机数探测法。开放地址法包括线性探测二次探测以及双重散列等方法。

设计思路:有冲突时就去寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到,并将数据元素存入。

含义:一旦冲突,就找附近(下一个)空地址存入。

具体实现:

1) 线性探测法

Hi=(Hash(key)+di) mod m  ( 1≤i < m )    其中: Hash(key)为哈希函数  m为哈希表长度  di 为增量序列 1,2,…m-1,且di=i

例:

关键码集为 {47,7,29,11,16,92,22,8,3},

设:哈希表表长为m=11; 哈希函数为Hash(key)=key mod 11; 拟用线性探测法处理冲突。建哈希表如下:

数据结构与算法18—哈希表(散列表)

解释:

① 47、7(以及11、16、92)均是由哈希函数得到的没有冲突的哈希地址;

② Hash(29)=7,哈希地址有冲突,需寻找下一个空的哈希地址:由H1=(Hash(29)+1) mod 11=8,哈希地址8为空,因此将29存入。

③ 另外,22、8、3同样在哈希地址上有冲突,也是由H1找到空的哈希地址的。其中3 还连续移动了两次(二次聚集)

int FindHash(SeqList* pL, KeyType K) { int c=0; int p=Hash(K); /*求得哈希地址*/ while(pL->data[p].key!=NULL_KEY && K!=pL->data[p].key && ++c<MAXNUM) p=Hash(K+c); if(K==pL->data[p].key) { printf("\n成功找到 %d", K); return p; /*查找成功,p返回待查数据元素下标*/ } else if(pL->data[p].key==NULL_KEY) { printf("\n无法找到 %d , 在位置 %d 插入。", K,p); pL->data[p].key = K; pL->n++; return p; } else { printf("\n无法找到 %d , 表已满。", K); return -1; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzjgwp.html