哈希之开散列,闭散列,多阶哈希,一致性哈希

一,哈希概念

哈希搜素:可以不经过任何比较,一次直接从表中得到搜素的元素。

二,散列

HASH(key) = key%m

哈希方法中使用的转换函数成为散列函数,构造出来的结构成为哈希表。

插入元素时:根据插入元素的关键码,计算出存储的位置。

搜素元素时:对元素的关键码进行同样的计算,把求得的函数值当做元素存储的位置,在结构中按此位置取元素比较,若关键码相同,搜素成功。

三,哈希冲突

上面的散列方式,有个很大的问题,当数据多的时候HASH(key) 会重复,这时候就不好插入了。

四,闭散列

闭散列,是用来解决哈希冲突的一种方法。

线性探测:当HASH(key)重复时,去探测下一个位置,如果下一个位置为空的话,插入。

二次探测:当HASH(key) 重复时,去找空位置,具体函数为,H1 = (H0+i^2)%m,其中H0是第一个关键码,m是表的大小,

H1是新位置。

          闭散列:这样的闭散列处理哈希冲突时不能随便删除已有的元素,若直接删除元素会影响其他元素的搜素,而且,当数据过多的时候,效率会很低。

          解决方法:可以定义一个结构体,把它的状态也放进去,(存在,删除,空),至于效率的问题可以采用负载因子解决,

          负载因子:a = 填入表中的元素个数/散列表长度,只要负载因子超过0,7就增容。

五,开散列

        开散列:也叫哈希桶,当哈希冲突时,我们可以在当前位置挂一个结点,用来存储它的值。

        问题:同样它也存在效率的问题,我们可以用素数表(经过别人大量测过的素数),来增容,在它下面挂红黑树,或者用联合解决。

六,多阶哈希

      多阶哈希:是通过多个数组来解决哈希冲突的,当一阶有数据的时候,就去下面的阶去找空位置。下面的这段是别人,我懒的画了。那么这个表的大小是如何获得的呢?举个列子,假如每阶最多有1000个元素,一共10阶,则算法选择十个比1000小的最大素数,从大到小排列,以此作为各阶的元素个数. 通过素数集中的算法得到的10个素数分别是: 997 991 983 977 971 967 953 947 941 937. 可见虽然是锯齿数组,各层之间的差别并不是很多.

       开散列和闭散列都有自己的优缺点, 现在我们考虑多阶哈希和开链法比较起来优势和劣势:

1.hash冲突处理的非常简单. 开链法其实都是找到位置他们的查找时间复杂度常规情况下都是O(1). 开链极端才会O(N)

2.有多个桶,使得空间利用率很高,多阶哈希并不需要一个很大的桶来减少冲突.

3.开链法的增容做的事情将所有节点都要重新挂. 但是多阶哈希可以动态增长空间,不断加入新的一阶,且对原来的数据没有影响.

4.不过相对来说,多阶哈希是提前开辟好空间,而哈希桶是来一个添加一个,所以多阶哈希比较占用空间.

当然多阶哈希也会有自己不足的地方,比如每次查询就必须固定N次的HASH处理,而且在极端的情况下,如果N次HASH后,得到的每一个

位置都被人占用了,那么存在不能插入的可能. 不过这种可能性非常之低,并且空间利用率往往都已经在80%以上了.

七,一致性哈希

一致性哈希是,1997年,哈弗大学提出来的,主要解决英特网的热点问题。多用于后台服务器中,当一台机器坏时,如果用普通的哈希,会导致,所有数据要转移,服务器会崩溃掉,其他可以看这篇博客,挺详细的。

其中一致性哈希满足两个点:单调性,和平衡性。

https://blog.csdn.net/a519640026/article/details/76157944

猜你喜欢

转载自blog.csdn.net/congjichukaishi/article/details/82502791