是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,记为 Hash(key) = Addr 这里的地址是数组下标、索引或内存地址等)。
散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突,这些发生碰撞的不同关键字称为同义词。一方面,设计得好的散列函数应尽量减少这样的冲突;另一方面,由于这样的冲突总是不可避免的,所以还要设计好处理冲突的方法。
取关键词的某个线性函数值为散列地址,即H(key) = a × key + b (a、b为常数)
适用情况:它适合关键字的分布基本连续的情况,若关键字分布不连续,空位较多,则会造成存储空间的浪费。
散列函数为:H(key) = key mod p(假定散列表的长度为m,取一个不大于m但是接近于m的质数p)
分析数字关键字在各位上的变化情况,取比较随机的位作为散列地址。
适用情况:这种方法适合于己知的关键字集合,若更换了关键字,需要重新构造新的散列函数。
这种方法取关键字的平方值的中间几位作为散列地址。具体取多少位要视实际情况而定,这种方法得到的散列地址与关键字的每位都有关系。因此使得散列地址分布比较均匀。
适用情况:适用于关键字的每位取值都不够均匀或均小于散列地址所需的位数。
开放定址法就是一旦发生冲突,就去寻找下一个空的散列地址。它的递推公式为:
其中H(key)为散列函数;i=0,1,2,...,k(k<=m-1);m表示散列表的长度;di表示增量序列。
这里增量序列的不同表示处理方式也不同,增量序列一旦被确立之后,处理方式也就确立了。通常,增量序列有以下四种取值方式:
(1)
线性探测法:当di=0,1,2,..,m-1时,称为线性探测法。
探测方式:
冲突发生时,顺序查看表中下一个单元(探测到表尾地址m- 1时,下一个探测地址是表首地址0),直到找出一个空闲单元(当表未填满时一定能找到一个空闲单元) 或查遍全表。
缺点:
线性探测法的探测方法会使大量元素在相邻的散列地址上”堆积”起来,这样大大降低了查找效率。
平方探测法:
当di=0,12,-12,22,-22,...,k2, -k2时,称为平方探测法,其中k<=m/2,散列
表长度m必须是一个可以表示成4k+ 3的素数,这样的方法又称二次探测法。
探测方式:
与线性探测法类似。但它可以避免出现“堆积”问题。
缺点:
由于di为某数的平方,不能探测到散列表上的所有单元,但至少能探测到一半单元。
再散列法:
当di= Hash2(key)时,称为再散列法,又称双散列法。需要使用两个散列函数。
探测方式:
当通过第一个散列函数H(key)得到的地址发生冲突时,则利用第二个散列函数Hash2(key)计算该关键字的地址增量。它的具体散列函数形式如下:
Hi= (H(key) + i×Hash2(key)) % m
初始探测位置H0= H(key)%m。i是冲突的次数,初始为0。
伪随机序列法:
当di=伪随机数序列时,称为伪随机序列法。
① 使用探测序列,有时计算的时间成本过高,导致散列表的处理性能降低
② 删除记录时较麻烦。不能随便物理删除表中的已有元素,因为若删除元素,则会截断其他具有相同散列地址的元素的查找地址。因此,要删除一个元素时,可给它做一个删除标记,
进行逻辑删除。但这样做的副作用是执行多次删除后,表面上看起来散列表很满,实际上有许多位置未利用,因此需要定期维护散列表,要把删除标记的元素物理删除。
所有关键字为同义词的记录存储在一个单链表中,称这种表为同义词子表,在散列表中只存储所有同义词子表的头指针。拉链法适用于经常进行插入和删除的情况。
① 对于记录总数频繁可变的情况,处理的比较好。
存储的记录是随机分布在内存中的,这样在查询记录时,相比结构紧凑的数据类型(比如数组),散列表的跳转访问会带来额外的时间开销。
查找成功时的平均查找长度是指找到表中已有表项的平均比较次数,它是找到表中各个已有表项的平均比较次数。
查找不成功的平均查找长度是指在表中找不到待查的表项,但找到插入位置的平均比较次数。它是在表中所有可能散列到的地址,上插入新元素时,为找到空位置而进行探查的平均次数。
Tips:散列表的平均查找长度与关键字个数n无关,而与装填因子a有关
下面我们来看一个例子:
Q:
用关键字序列{2, 34,23,11, 25, 35,12,14}创建一个Hash表,装填因子a为1/2,试确定表长m,采用除留余数法构造Hash函数,采用链地址法来处理冲突,并计算查找成功与不成功时的平均查找长度ASL1和ASL2(只将与关键字的比较计算在内)。
由装填因子a的定义知道,a=n/m, 其中n为关键字个数,m为表长,因此可以求出m为16。
除留余数法的Hash函数构造公式为H(key)=key mod p,其中p为不大于表长的最大素数,因表长m为16,所以p取13,Hash函数为H(key)=key Mod 13。
用(2)中构造的Hash函数并用链地址法处理冲突所建立的Hash过程如下:
2 mod 13 = 2,将2插在地址为2的链表表尾
34 mod 13 = 8,将34插在地址为8的链表表尾
23 mod 13 = 10,将23插在地址为10的链表表尾
11 mod 13 = 11,将11插在地址为11的链表表尾
25 mod 13 = 12,将25插在地址为2的链表表尾
35 mod 13 = 9,将35插在地址为9的链表表尾
12 mod 13 = 12,将12插在地址为12的链表表尾
14 mod 13 = 1,将14插在地址为1的链表表尾
ASL1=(1+1+2+1+1+1+1+1)/8=1.125
ASL2=(0+1+2+0+0+0+0+0+1+1+1+1+1)/13=0.615
( 2014统考)用哈希(散列)方法处理冲突(碰撞)时可能出现堆积(聚集)现象, 下列选项中,会受堆积现象直接影响的是()
Tips:
产生堆积现象,即产生了冲突。平均查找长度会因为堆积而增大。
(2018统考真题)现有长度为7、初始为空的散列表HT,散列函数H(k)=k % 7,用线性探测再散列法解决冲突。将关键字22, 43, 15 依次插人到HT后,查找成功的平均查找长度是()。
Tips:
根据题目要求可以画出散列表,根据散列表可以得到ASL成功=(1+2+3)/3=2
(2019统考真题)现有长度为 11且初始为空的散列表HT,散列函数是H (key)=key%7,采用线性探查(线性探测再散列)法解决冲突。将关键字序列87, 40, 30, 6, 11,22, 98, 20依次插入HT后,HT查找失败的平均查找长度是()。
Tips:由于H(key)=0~6,查找失败时对应的可能地址有七个,要特别注意的是,散列函数不可能计算出地址7。
故ASL失败=(9+8+7+6+5+4+3)/7=6
抓码计算机考研qq群
总群:625590924
广大:1143982604
暨大:1071137230
广工:938111325
华工:428389734
深大:729770764
浙大:978938582
厦大:1125268501
中大:921801084
南航:281118241
华农:515681663
重邮:736197896
北邮:1126650806
南邮:1109929146
广外:976231252
东北大学:1128523098
华南师大:428389734
南昌大学:923249141