程序员

数据结构之散列表

2018-11-13  本文已影响0人  橘子_好多灰

1、散列函数

原则

定义

1.散列函数计算得到的散列值是一个非负整数。
2.若key1=key2,则hash(key1)=hash(key2)
3.若key≠key2,则hash(key1)≠hash(key2)

如何设计

1.要尽可能让散列后的值随机且均匀分布,这样会尽可能减少散列冲突,即便冲突之后,分配到每个槽内的数据也比较均匀。
2.除此之外,散列函数的设计也不能太复杂,太复杂就会太耗时间,也会影响到散列表的性能。

常见方法

直接寻址法

取关键字key的某个线性函数为散列地址,如Hash(key) = key 或 Hash(key) = A*key+B; A,B为常数。
如:有一个从1到100岁的人口数字统计表,其中,年龄作为关键字,哈希函数取关键字自身。但这种方法效率不高,时间复杂度是O(1),空间复杂度是O(n),n是关键字的个数。

除留取余法

关键值除以比散列表长度小的素数所得的余数作为散列地址。Hash(key) = key % p;
p的选取非常关键,p选择的好的话,能够最大程度地减少冲突,p一般取不大于m的最大质数。

平方取中法

先计算构成关键码的标识符的内码的平方,然后按照散列表的大小取中间的若干位作为散列地址。
如:有以下关键字序列{421,423,436},平方之后的结果为{177241,178929,190096},那么可以取{72,89,00}作为Hash地址。

折叠法

把关键码自左到右分为位数相等的几部分,每一部分的位数应与散列表地址位数相同,只有最后一部分的位数可以短一些。把这些部分的数据叠加起来,就可以得到具有关键码的记录的散列地址。
如:比如关键字是9876543210,散列表表长是3位,将其分为四组,然后叠加求和:987 + 654 + 321 + 0 = 1962,取后3位962作为散列地址。

随机数据法

选择一个随机函数,取关键字的随机函数作为它的哈希地址。
H(key)=random(key),其中random为随机函数。通常用于关键字长度不等时采用此法。

数学分析法

设有N个d位数,每一位可能有r种不同的符号。这r种不同的符号在各位上出现的频率不一定相同,可能在某些位上分布均匀些,每种符号出现的机会均等;在某些位上分布不均匀,只有某几种符号经常出现。可根据散列表的大小,选取其中各种符号分布均匀的若干位作为散列地址

2、冲突解决

开放寻址

线性探测

二次探测

伪随机探测

再hash法

链地址法

其他

3、动态扩容

装载因子
时间复杂度:摊还分析法
如何避免低效扩容

4、工业级的散列表

要求

方案

5、位图

定义

思想

优点

运算效率高,不许进行比较和移位;
占用内存少,比如N=10000000;只需占用内存为N/8=1250000Byte=1.25M。

缺点

所有的数据不能重复。即不可对重复的数据进行排序和查找。
比如:00000000000000000000000000010100 标注了2和4。

应用

*   排序(非重复)
*   去重
*   快速查询
*   布隆过滤器: 见:[http://www.cnblogs.com/dolphin0520/archive/2012/11/10/2755089.html](http://www.cnblogs.com/dolphin0520/archive/2012/11/10/2755089.html)
上一篇 下一篇

猜你喜欢

热点阅读