哈希冲突应对之多阶哈希表

哈希表在处理数据查找、判断数据是否存在时非常的高效,但是哈希表在插入时可能会出现哈希冲突。而解决哈希冲突主要两种方式就是开散列与闭散列的解决方式,两者各有优点与缺点。而今天要说的解决哈希冲突的方式是建立多阶哈希表!


多阶哈希表

其实所谓多阶哈希表可以理解成多个数组,但是这些数组都是特殊的。这些数组的长度不一致,每个数组所能存储的元素个数都是一个素数(利用素数作为元素个数是避免产生哈希冲突的一种方式)。下面来画一个多阶哈希的简易图。

这里写图片描述

由于各阶哈希表的长度都不相同,所以相同的 key 在各阶哈希中根据法则得到的映射也大多不同,并且由于各个哈希表长度都为素数。这样来看多阶哈希表产生哈希冲突的可能就更小了。

这里的每一阶哈希表的长度从第一阶开始自上到下开始递减,并且都是素数。比如说有十阶哈希表,每阶哈希表最多存放 1000 个元素,那么就找出小于 1000 的最大的十个素数并排序,依次从大到小作为各阶哈希表的长度。

查找

在查找的时候,从第一阶开始,利用数据的 key 来求出对应的位置,看对应下标下是否为空,如果是空,那么一定不存在这个数据;如果不为空,再比较 key 的值,如果相等,证明找到了,如果不相等证明发生了哈希冲突,那么从第二阶继续寻找,以此类推,直至找到最后一阶。

插入

插入的时候,如果没有发生哈希冲突,那么照常插入。如果一旦发生哈希冲突,那么就在下一阶进行插入判断。多阶哈希在处理哈希冲突时非常的简单,当然开散列哈希桶的方式处理哈希冲突也很简单。

增容

但是一旦需要增容的时候,多阶哈希的优点就体现出来了。不论是开散列还是闭散列,在增容的时候都需要开辟一片更大的空间,并且将之前空间内的数据全部进行从新计算并拷贝,这个过程是一个非常耗费时间与空间的过程,并低效!而多阶哈希在增容时只需要再多增加一阶哈希表即可,并不需要对之前的所有数据进行搬运,这就能够节省很大的效率。

与开散列哈希桶的比较

哈希桶与多阶哈希相比来说,两者处理哈希冲突的方式都很简单,但是在增容问题上,哈希桶却不占优势,因为它需要一个数据搬迁的过程,而多阶哈希能够很轻松的解决增容问题。但是多阶哈希也是有缺点的,哈希桶是来一个插入一个,对空间的利用率很高,并不会浪费很多空间。而多阶哈希在创建时就需要开辟一大段空间,这对空间无形中是一种浪费。插入时如果有一种极端情况导致每一阶哈希表都发生哈希冲突,那么直到最后一阶都无法插入,这个时候如何处理?但是哈希桶就不会出现这种问题。

解决极端情况无法插入问题

在多阶哈希表内有很多元素的时候,此时插入新的数据,发现每阶哈希都发生哈希冲突无法插入,那么这个时候如何解决?其实在哈希表内有很多元素的时候,这个时候发生这种极端问题后,可以采用类似扩容的方法,再创建一阶哈希表进行存储,由于已经有很多元素了,所以这时候创建一阶新的哈希完全是可以的。

但是会不会有这样一种情况呢?十阶哈希插入十一个元素,插入完毕前十个元素后,从第十一元素开始跟前十阶都发生哈希冲突(这里只是举个例子,这种极端情况基本上没可能),此时如果开辟一阶新的哈希表是不是代价就有点大了。那么如何解决?

这里我的思路是将多阶哈希与开散列哈希桶相结合使用。

比如说是十阶哈希,那么前九阶哈希仍旧跟之前相同,不过最后一阶哈希采用哈希桶的方式,如果插入一个数据十阶哈希全部发生哈希冲突,那么在最后一阶进行类似于哈希桶的操作。

这里写图片描述


欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!

猜你喜欢

转载自blog.csdn.net/liuchenxia8/article/details/80569009