数据结构:散列(Hash列表)

所谓散列,就是将一个数hash之后按照值去放入指定房间。此时当我们需要访问时,我们只需要将访问值hash后按值寻找即可,所以其运行效率极高。但是当开辟空间被占用过高后,hash将容易发生碰撞,此时如何处理决定了接下来的运行效率。
1.分离链接法
分离链接指当出现相同时,我们可以通过链表将其链接起来。此时当我们需要访问时按照hash值去找到对应链表,按照顺序访问直到找到为止。
值得注意的是,新加入的元素放在链表头部,因为经验表明:新加入的元素被访问概率最大。
具体情况如下图所示。
 
2.线性探测法
线性探测法提出,当我们遇到已经插入的,则延续向下寻找一直直到找到一个空位为止。
这会导致一个弊端:即使表相对较空,这样占据的位置也容易形成聚在一起的区块。这将直接导致在访问时产生大量的向下访问,进而减低运行效率。
对于插入不成功的查找大约为:1/2(1+1/〖(1-λ)〗^2 )
对于成功查找的则是:1/2(1+1/(1-λ))
通过实验表明,加入表多于一半被填满,则此方法不适合。
3.平方探测法
平方探测法是当插入已有位置时,再次对末尾数字进行平方去寻找下一个位置。而不是通过线性探测向下寻找。
值得注意的是:当表的大小为素数,且至少有一半为空,则总能插入一个新的元素,而不会一直平方循环。
所以,常常会把表的大小设置为一个素数。
在使用平方探测法时,我们不能实现及时删除,否则将会进行大量的find操作,降低运行速率。而是采用懒惰删除,即只做标记将要删除这个数,并不进行寻找。等到下次访问时遇到了再进行删除。
然而,这仍然存在问题:这可能导致散列到同一位置上的元素将探测相同备选单元,被称作二次聚集。
4.双散列
双散列指出当插入发生重复已存在时,则选择第二个〖hash〗_2函数进行再次散列,寻找新的一个位置。所以对于双散列来说,如何选择好第二个〖hash〗_2函数十分关键。如果〖hash〗_2选择的好,理论上期望探测次数与随机一样。然而平方探测法相比起来更加简单并且快速,尤其是针对字符串等计算散列十分耗时。
5.再散列
再散列是指当散列已经较满时,则将散列扩容至两倍,并对其中所有值进行散列计算并放入新的散列中。值得注意的是,虽然再散列操作十分昂贵,然而由于其发生次数较少,所以不会过多影响效率。如何使用再散列决定了这个散列的时间效率了。
可以以多种方式实现:(1)表满一半即再散列(2)插入失败再散列(3)途中策略:散列达到某一装填因子的进行再散列
6.完美散列(下文的导论)
定理:如果N个球被放入M=N^2个箱子中,那么没有箱子装有多于1个球的概率大于1/2。
定理:如果将N项放入包含N个箱子的主散列表中,那么二级散列表的总大小期望值最多为2N。
7.杜鹃散列
通过上述讨论,我们知道,如果将N项随机放入N个箱子中,那么含球最多的箱子的期望球数位Θ(log⁡N/log⁡log⁡N  )。而后数学家发现:如果在每次投掷中随机选择两个箱子并投入较空的箱子中时,则最大箱子球数只是Θ(log⁡log⁡N ),这是一个很小的数。基于此,杜鹃散列被提出。
杜鹃散列将设立两个散列表,并对每一个输入值分别求两个的散列位置。
而后,将其插入第一个散列表中。倘若第一个散列表中存在重复的,则将其重复的丢入另一个散列表中。若是继续遇到重复的则继续相互调换。此时,则会涉及到一个问题:可能导致死循环互相调换。不过值得庆幸的是,这个可能性很低。
所以,需要确定一个替换的期望次数,值得指出,需要多于O(log⁡N)次位置替换的可能性很低,所以当高于O(log⁡N)时,即可进行再散列。
8.跳房子散列
跳房子散列额外加入了一盒Hop值,其中储存了一个多位二进制数(一般由计算机体系的基础变量大小决定,下文以四位为例),这四位中哪一位是1表示往下第几位是应该插入这个位置的值。这样一来每个数都可以插入到多个位置,而相比于线性探测法,因为已经记录了Hop值所以能更快确定下面的位置。倘若下面四位都用完了,那么则进行回溯每个进行调整直到符合为止。倘若无法调整到合适,则将进行再散列。
9.通用散列
通用散列指:如果对于任意x≠y,散列函数簇H中使得h(x)=h(y)的散列函数h的个数最多为(|H|)/M,则称散列函数簇H是通用的。
定理:散列函数簇:H={H_(a,b) (x)=((ax+b)mod p)mod M,where 1≤a≤p-1 and 0≤b≤p-1}是通用的
10.可扩散列
这里讨论一种情况:当数据太大装不进主存时,若存入磁盘如何进行更快的访问。
此时与B+ Tree相同,提出了可扩散列的方法。
其将会把所有key转为二进制。并且将会有四个父节点,分别指向头两位是00,头两位是01,头两位是10,头两位是11的四种情况。并且每个叶节点只储存M=4个数据。
倘若插入后超过储存上限,则将会将父节点拆分为xx0与xx1两种情况。例如拆分01则会得到010与011两个叶子节点,由此进行向下划分。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值