哈希查找

来源:互联网 发布:什么软件外卖货到付款 编辑:程序博客网 时间:2024/05/16 13:11
转自:点击打开链接Hash快速查找1.哈希表的概念:   哈希是一种重要的存储方法,也是一种重要的查找方法。   它的基本思想是:以关键字K为自变量,通过一个确定的函数f,计算出对应的函数值f (k),把这个值解释为关键字等于K的结点的存储地址。查找时,再根据要查找的关键字用同样的函数计算地址,然后到相应的存储单元取出要查找的结点。按这个思想建立的表,称为哈希表,称函数f 为哈希函数,称f (k)的值为哈希地址。   哈希表实例:已知线性表的关键字集合为:   S = {and,begin,do,end,for,go,if,then,until }   则可设哈希表为:   char HT[26][8]   哈希函数H(key)的值,可取关键字key中第一个字母在字母表中的序号(0~25),即 H(key) = key[0]- 'a'    哈希函数是一个映射,其设定可以很灵活,只要使得任何关键字的哈希函数值都落在表长允许范围内即可。   对不同关键字可能得到同一哈希地址,这一现象称为"冲突",而发生冲突的关键字对于该哈希函数来说,称为"同义词"。因关键字集合比哈希表长度大,故冲突不可避免。
2. 哈希函数的构造方法:    2.1 直接定址法:   取关键字或关键字的某个线性函数值为哈希地址。即: H(key) = key 或 H(key) = a*key+b 实例:某大学从1960年开始招生,有历届招生人数统计表,其中 以年份为关键字。则哈希函数可设计为:H(key) = key - 1959 直接定址法由于关键字与存储地址存在一一对应关系,因此,不会 发生冲突现象。   2.2 除余法:   选择一个适当的正整数P(P≤表长),用P 去除关键字,取所得余数作为哈希地址。即:H(key) = key % P (P ≤ 表长) 除余法的关键是选取适当的P,一般选P为小于或等于哈希表的长 度m的某个素数为好,或者为不含20以下素素的合数
。   例: m = 8,16,32,128,256,512 P = 7,13,31,127,251,503 除余法不仅可以直接对关键字取模,也可在折叠、平方取中等运算 之后取模。   2.3 平方取中法:   取关键字平方后的中间几位为哈希地址。由于一个数的平方的中间几位与这个数的每一位都有关,因而,平方取中法产生冲突的机会相对较小。平方取中法中所取的位数由表长决定。   例: K = 456 , K2 = 207936 若哈希表的长度m=102,则可取79(中间两位)作为哈希函数值。   2.4 折叠法:   把一个关键码分成位数相同的几段(最后一段的位数可以, 不同),段的长度取决于哈希表的地址位数,然后将各段的 叠加和(舍去进位)作为哈希地址。   折叠法又分为移位叠加边界叠加两种。其中,移位叠加是将 各段的最低位对齐,然后相加;而边界叠加则是两个相邻的段沿边界来回折叠,然后对齐相加。   例:关键字K=58242324169,哈希表长度为1000,则将此关键字分成三位一段,两种叠加结果如下:582+ 423+ 241+69=315,582+324+ 241+96= 243    当关键字位数很多,而且关键字中每一位上数字分布大致均匀时,可以使用折叠法。    2.5 数字分析法:   假设关键字是以r为基的数,并且哈希表中可能[TA6:除余法] 出现的关键字都是事先知道的,则可取关键字中的若干位组成哈希地址。

 3. 处理冲突的方法: 3.1 开放定址法:开放定址法。如果H(k)已经被占用,按如下序列探查:(H(k)+p⑴)%m   (H(k)+p⑵%m,…,(H(k)+p(i))%m,…其中,H(k)为哈希函数, m为哈希表长,p(i)为探查函数。在 H(k)+p(i-1))%m的基础上,若发生冲突,则使用增量 p(i) 进行新的探测,直至无冲突出现为止。根据探查函数p(i)的不同,开放定址法又分为:线性探查法 p(i) = i     (i=1,2,3,…)随机探查法p(i)=随机数双散列函数法双散列函数H(key) ,HP(key)若H(key)出现冲突,则再使用HP (key)求取散列地址。探查序列为:H(k),H(k)+ HP(k),…,H(k)+ i*HP(k))
  3.2 再哈希法:  基本做法:当冲突发生时,使用另一个哈希函数计算得到一个新的哈希地址,直到冲突不再发生时为止,即  Hi = RHi(key) i = 1,2,…,k  其中,RHi均是不同的哈希函数。  这种方法的优点是不易产生聚集,但缺点是增加了计算时间。 3.3 链地址法:  基本做法:将所有关键字为同义词的结点链接在同一个单链表中。若选定的哈希函数所产生的哈希地址为0~m-1,则可将哈希表定义成一个由m个链表头指针组成的指针数组。

 这种方法的优点是:    ① 不产生"堆集"。    ② 由于结点空间是动态申请的,故更适合于造表前无法确定表长的情况。    ③ 从表中删除结点容易。 3.4 公共溢出区法:  基本做法:假设哈希函数的值域为[0,m-1],则设向量HashTable[0,m-1]为基本表,每个分量存放一个记录,另设立向量OverTable[0,v]为溢出表。所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都被填入溢出表中。在哈希表上进行查找的过程和建表的过程基本一致。假设给定的值为K,根据建表时设定的哈希函数H,计算出哈希地址H(K),若表中该地址对应的空间未被占用,则查找失败,否则将该地址中的结点与给定值K比较,若相等则查找成功,否则按建表时设定的处理冲突方法找下一个地址,如此反复下去,直到找到某个地址空间未被占用(查找失败)或者关键字比较相等(查找成功)为止。 

 4.HASH查找的程序实现:4.1 哈希查找的操作步骤:⑴用给定的哈希函数构造哈希表⑵根据选择的冲突处理方法解决地址冲突;⑶在哈希表的基础上执行哈希查找。4.2 查找:  在哈希表上进行查找的过程和建表的过程基本一致。假设给定的值为K,根据建表时设定的哈希函数H,计算出哈希地址H(K),若表中该地址对应的空间未被占用,则查找失败,否则将该地址中的结点与给定值K比较,若相等则查找成功,否则按建表时设定的处理冲突方法找下一个地址,如此反复下去,直到找到某个地址空间未被占用(查找失败)或者关键字比较相等(查找成功)为止。

4.4 查找算法演示: 4.5 性能分析:  虽然哈希表是在关键字和存储位置之间建立了对应关系,但是由于冲突的发生,哈希表的查找仍然是一个和关键字比较的过程,不过哈希表平均查找长度比顺序查找要小得多,比二分查找也小。  查找过程中需和给定值进行比较的关键字个数取决于下列三个因素:哈希函数、处理冲突的方法和哈希表的装填因子。  哈希函数的"好坏"首先影响出现冲突的频繁程度,但如果哈希函数是均匀的,则一般不考虑它对平均查找长度的影响。
  对同一组关键字,设定相同的哈希函数,但使用不同的冲突处理方法,会得到不同的哈希表,它们的平均查找长度也不同。  一般情况下,处理冲突方法相同的哈希表,其平均查找长度依赖于哈希表的装填因子α。  显然,α越小,产生冲突的机会就越,但α过小,空间的浪费就过多。通过选择一个合适的装填因子α,可以将平均查找长度限定在一个范围内。

二次探查法 p(i)=(-1)^(i-1)*((i+1)/2)^2,探查序列依次为:(1, -1,4, -4, 9 …)

0 0
原创粉丝点击