散列/哈希总结

匿名 (未验证) 提交于 2019-12-03 00:22:01

哈希函数很强大,最近算法课老师讲了哈希函数的一系列应用。这里总结一下。

一、哈希表

哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构。它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度。这个映射函数就做散列函数,存放记录的数组叫做散列表。以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中。 哈希表存储的是键值对,其查找的时间复杂度与元素数量多少无关,哈希表在查找元素时是通过计算哈希码值来定位元素的位置从而直接访问元素的,因此,哈希表查找的时间复杂度为O(1),最坏的情况下查找一个元素的时间与在链表中查找一个元素的时间相同。最坏的情况下都是O(N)。有一个常用的概念定义为load factor(装载因子)算法导论中给的定义为:给定一个能存放n个元素的,具有m个槽位的散列表T。定义T的装载装载因子a为n/m,即一个链中平均存储的元素。一个好的散列函数应满足简单一致散列的假设。每个关键字都等可能的散列到m个槽位的任何一个之中去,并与其它的关键字已被散列到哪一个槽位中无关。

二、散列函数

1.除法散列法

在用来设计散列函数的除法散列法之中,通过取k除以m的余数,来将关键字k映射到m个槽中去,定义散列函数为

                                                            h(k)=k mod m

例如,如果散列表的大小为12,所给关键字k=100,h(k)=4。这种方法只要一次除法操作,所以比较快。

当应用除法散列时,要注意m的选择。例如,m不应该是2的幂。因为如果m为2的幂。则h(k)就是k的p个最低位数字。除非我们事先知道,关键字的概率分布使得k的各种最低p位的排列形式的可能性相同。否则在设计散列函数时,最好考虑关键字所有位的情况。我们通常选择m的值常常是与2的整数幂不太接近的质数。

2.乘法散列法

构造散列函数的乘法方法包含两个步骤。第一步,用关键字k乘上常数A(0<A<1),并抽取kA的小数部分。然后用m乘以这个值,再取结果的底(floor)总之,散列函数为其中‘kA mod 1’即 kA 的小数部分。

                                        h(A)=m(kA mod 1)

乘法方法的一个优点是对m的选择没有什么特别的要求。一般我们选择A约为0.618(黄金分割点).

3.全域散列

如果让某个与你作对的人来选择要散列的关键字,那么他会选择全部散列到同一个槽中的n个关键字。唯一有效地改进方法是随机地选择散列函数,是指独立于要存储的关键字,这种方法称之为全域散列。其基本思想是在执行开始时,就从一组仔细设计的函数中,随机地选择一个座位散列函数。随机化保证了没有哪一种输入会始终导致最坏情况的放生。使得即使对同一个输入,算法在每一次执行时的状态也都不一样。主要过程如下:

设H为有限的一组散列函数,它将给定的关键字域映射到{0,1,...,m-1}这样的一个函数组称为全域的。如果对每一对不同的关键字k,l满足h(k)=h(l)的散列函数的个数至多为|H|/m。换言之,如果从H中随机地选择一个散列函数,当关键字k!=l是,亮着发生碰撞的概率不大于 1/m。

三、处理冲突的方法

1.链地址法。

链地址法也成为拉链法。其基本思路是:将所有具有相同哈希地址的而不同关键字的数据元素连接到同一个单链表中。如果选定的哈希表长度为m,则可将哈希表定义为一个有m个头指针组成的指针数组T[0..m-1],凡是哈希地址为i的数据元素,均以节点的形式插入到T[i]为头指针的单链表中。并且新的元素插入到链表的前端(头插法),这不仅因为方便,还因为经常发生这样的事实:新近插入的元素最优可能不久又被访问。

链地址法特点
(1)拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短; 
(2)由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况; 
(3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间; 
(4)在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将被删结点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。因此在用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。

2.开放定址法――线性探测

线性探测法的地址增量di = 1, 2, ... , m-1,其中,i为探测次数。该方法一次探测下一个地址,知道有空的地址后插入,若整个空间都找不到空余的地址,则产生溢出。

线性探测容易产生“聚集”现象。当表中的第i、i+1、i+2的位置上已经存储某些关键字,则下一次哈希地址为i、i+1、i+2、i+3的关键字都将企图填入到i+3的位置上,这种多个哈希地址不同的关键字争夺同一个后继哈希地址的现象称为“聚集”。聚集对查找效率有很大影响。

3.开放地址法――二次探测

二次探测法的地址增量序列为 di = 12, -12, 22, -22,… , q2, -q(q <= m/2)。二次探测能有效避免“聚集”现象,但是不能够探测到哈希表上所有的存储单元,但是至少能够探测到一半。




转载请标明出处:散列/哈希总结
文章来源: 散列/哈希总结
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!