散列表分析

许多查询操作的运行时间都是Θ(lgn) , Θ(n),而直接寻址表和散列表更近一步


直接寻址表

在直接寻址表中关键字k被存在槽k中
在这里插入图片描述在这里插入图片描述
可以看增删改的操作只需要Θ(1)时间内完成,但如果U很大,那么计算机存储这么多不太可能


散列表

动态散列表

在直接寻址表中关键字k被存在槽h(k)中
在这里插入图片描述
h就是散列函数,散列函数缩小了数组下标的大小,但可能发生h(k1)=h(k2)的情况,即被函数映射到同一个槽中,这就是冲突,所以散列表的关键点就是解决冲突

解决冲突方法一:链接法(chaining)

在这里插入图片描述

一丶链接法性能分析

装载因子:n个元素,m个槽,装载因子就是 α=n/m,也就是一个链的平均存储元素数

散列方法的平均性能依赖于所选取的散列函数h将所有的key分布在槽的均匀程度

接下来我们先分析一下分析的是简单均匀散列
就是给定一个元素等可能的散列到m个槽的任何一个,与其他元素无关,概率均为1/m
在这里插入图片描述

最坏情况运行时间,假如n个元素在一个槽
Θ(n)
一次成功所查找所需的平均情况运行时间: Θ(1+α)
1 为计算机散列值,α 为平均情况下需要搜索的链表长度n/m
所以α=O(1) 即 n≤cm ,也就是说槽数需要是元素数的常数倍,才能为 Θ(1)

二丶选择散列函数

给定一个key等可能的散列到m个槽的任何一个(key的分布不影响均匀散列)

1. 除法散列法

h(k)=k mod m
m

2. 乘法散列表

H是一个哈希函数集合,#XXX:代表XXX的数量
#{h∈H,h(x)=h(y)}≤ #H/m

3. 全域散列(重点)

使用的是不只一个散列函数,每次操作时都是随机选取一个散列函数来进行操作

  1. 随机化保证了没有哪一种输入会导致最坏的运行情况。·比如你再h1函数中,所有的key都被映射到同一个槽中,这是最坏的;但是假如在h2函数中,可能不是这样的。
  2. 即便你每次输入相同的序列算法每一次执行的情况都不同,这样确保了有较好的平均情况性能
全域散列性能分析

在这里插入图片描述
使得两个不同key被映射到同一个槽的函数数量最多为:|H|/m,也就是说随机选择一个散列函数,两个不同key被映射到同一个槽的概率:1/m【下面的推理需要用到此结论】

随机从H中选择函数h,现在我们假设n个key已经散列入m个槽中,对于给定的key :k

  1. 若k在表中,则k被散列到其中链表的期望长度≤α=n/m

  2. 若k不在表中,则k被散列到其中链表的期望长度<1+α=1+n/m

原本想用Yk的所有可能,求概率,直接加权平均算期望,但是没有找到公式来表示概率,所以下面是书上的方法
在这里插入图片描述

构造全域散列

注:方法不唯一,这是经典
让槽数为素数m,把全域里面的任意k分解为r+1位即 < k0,k1,…,kr > ki,k1,…,kr就是k的m进制,只不过每一位顺序可以乱
然后随机选取一个 a = < a0,a1,…,ar >

在这里插入图片描述
在这里插入图片描述
这个函数多大也就是前面说的H多大=mr+1

我们需要证明下面是全域的【难点】

解决冲突方法二:开放寻址法

所有元素都在散列表中, 没有链
为了插入元素,我们需要连续地检测散列表,称为探测,知道找到一个空槽存放关键字

一丶开放寻址法分析

均匀散列,给定一个装载因子为 α=n/m<1,对于一次不成功的查询,其期望的探查次数至多为1/(1-α)
在这里插入图片描述

二丶函数选择

线性探测

h(k.i)=[ h(k,0)+ i ]mod m

容易出现集群
前面的i个槽已被占用,那么下一个被占用的概率是 (i+1)/m,所有连续占用的槽会越来越长,因而平均查找时间也越来越大

双重探测

h(k.i)=[ h1(k)+ i × h2(k) ]mod m

两个散列函数h1和h2
经常取m=2r
h2(k)值取奇数

静态表:完全散列

第一级使用全域哈希

发布了124 篇原创文章 · 获赞 92 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_42146775/article/details/102663598