哈希表总结
2016-05-27 08:00
211 查看
一、哈希表/散列表
简单的来说将数据按规律放,然后按照规律来查找的这么一个存放数据的表它通过一个关键值的函数将所需的数据映射到表中对应的位置来存放数据和访问数据
这个映射的函数就叫做散列函数
这个存放记录的表就叫做散列表
二、构造哈希表的方法
1、.直接定址法
取关键字的某个线性函数为散列地址,Hash(Key)= Key 或 Hash(Key)= A*Key + B,A、B为常数。优点:简单没有哈希冲突
缺点:所开辟的空间过大,利用率不高
2、除留余数法
取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址。Hash(Key)= Key % P。优点:空间利用率高
缺点:设计复杂,要处理哈希冲突
三、哈希冲突/哈希碰撞
不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突。任意的散列函数都不能避免产生冲突四、影响哈希表效率的因素
(1)哈希函数是否均匀(2)处理冲突的方法
(3)哈希表的负载因子(简单的来说就是填入表中的元素个数/散列表的长度)
下面这幅图片是载荷因子的定义:
五、处理哈希冲突的闭散列的方法
1、线性探测
简单的来说就是遇到哈西冲突就查找下一个位置,看位置上是否有数据,假如有则继续查找,假如没有则将数据放入到当前位置局限性:引发洪水式的冲突,冲突越来越多,找的越来越慢(因为找到的是一片冲突,找到空才停下来),效率低
具体过程如图所示:
2、二次探测
以二次方的形式进行探测具体过程如下图所示:
六、处理哈希冲突的开链法(哈希桶)
闭散列最大的局限性就是空间利用率低,例如载荷因子为0.7,那么仍有0.3的空间未被利用使用开链法可以使载荷因子为1,每个链上都挂常数个数据,对于哈希表的开链法来说,其开的空间都是按素数个依次往后开的空间
· 那么什么时候扩容呢?当每个链上都挂上数据之后,载荷因子为1的时候,就可以开始扩容了
具体过程如下图所示:
七、优化
对于除留余数法,capacity的选择很重要,选择好的话可以大大降低发生哈希冲突的概率,所以使用素数表对齐做哈希表的容量,降低哈希冲突;const int _PrimeSize = 28; static const unsigned long _PrimeList[_PrimeSize] = { 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }
相关文章推荐
- Windows Powershell使用哈希表
- 探索PowerShell (八) 数组、哈希表(附:复制粘贴技巧)
- 轻松学习C#的哈希表
- PHP内核探索:哈希表碰撞攻击原理
- php内核解析:PHP中的哈希表
- java中哈希表及其应用详解
- C#中HashTable的用法
- 哈希函数
- Qt中QSet的使用
- 数据结构-散列表(Hash Table)的C++实现模板
- 数据结构——哈希表
- Two Sum,3Sum,3Sum Closest,4Sum
- 哈希表
- Java-Majority Element
- 哈希表及处理冲突的方法
- 常用算法C#实现:字符串包含问题
- 【Redis基本数据结构】字典实现
- 探测法的哈希表的C++实现(最新修改)
- [leetcode] Contains Duplicate 判断一数组是否有重复元素
- Zobrist哈希,研究棋类博弈必须了解的一个小工具