01哈希表

1. Hash Table

​ 咱们都知道,二叉树、红黑树等数据结构,它们的查找都是先从根节点开始查找,从节点取出数据或者索引与查找值进行比较。数组

​ 那么,有没有一种函数H,根据这个函数和查找关键字 Key,能够直接肯定查找值所在的位置,而不须要一个个比较。这样叫“预先知道” Key 所在的位置,直接找到数据,提高效率。即:数据结构

地址index = H(key)dom

说白了,hash函数功能就是根据 key 计算出应该存储地址的位置,而哈希表是基于哈希函数创建的一种查找表。函数

2. 哈希函数的构造方法

​ 根据前人经验,统计出集中经常使用 hash 函数构造方法设计

2.1. 直接定制法

​ 哈希函数为关键字的线性函数,如 H(key) = a * key + b,这种构造方法比较简单,均匀。可是有很大限制,仅限与地址大小 = 关键字集合的状况。指针

2.2. 数字分析法

​ 假设关键字集合中的每一个关键字 key 都是由s位数字组成(k1,k2,……,kn),分析 key 中的全体数据,并从中提取分布均匀的若干位或他们的组合构成全体。code

​ 使用举例:假设要保存的集合中 key 由 5 位不一样的数字构成。而且这些数字分布均匀,咱们能够提取其中一位,表明数据保存的地址。H(key) = key % 100000。索引

​ 此种方法一般用于数字位数较长的状况,要求数字存在必定的规律,其次必须知道数字的分布状况。hash

2.3. 平方取中法

​ 若是关键字的每一位都有某些数字重复出现频率很高的现象,能够先求关键字的平方值,经过平方扩大差别,然后取中间数位做为最终存储地址。table

​ 使用举例:

​ 好比:key = 1234 1234^2 = 1522756 取 227 做hash地址

​ 好比:key = 4321 4321^2 = 18671041 取 671 做hash地址

​ 这种方法适合事先不知道数据而且数据长度较小的状况。

2.4. 折叠法

​ 若是数字的位数不少,能够将数字分割为几个部分,取他们的叠加和做为hash地址。

​ 使用举例:

​ 好比 key=123 456 789

​ 咱们能够取 1368(123+456+789=1368) 做为 hash 地址。

该方法适用于数字位数较多且事先不知道数据分布的状况。
2.5. 除留余数法(最经常使用)

​ H(key)=key MOD p (p<=m m为表长) 很明显,如何选取p是个关键问题。

​ 使用举例
好比咱们存储3 6 9,那么p就不能取3
由于 3 MOD 3 == 6 MOD 3 == 9 MOD 3
p应为不大于m的质数或是不含20如下的质因子的合数,这样能够减小地址的重复(冲突)

​ 好比key = 7,39,18,24,33,21 时取表长m为9 p为7 那么存储以下:

index 0 1 2 3 4 5 6 7 8
Key 7 21(冲突后移) 24 39 18(冲突后移) 33(冲突后移)
2.6. 随机数法

​ H(key)= random (key) 取关键字的随机函数为它们的散列地址。

哈希函数设计的考虑因素
  • 计算散列地址所须要的时间(即 hash 函数自己不要太复杂)
  • 关键字的长度
  • 表长
  • 关键字分布是否均匀,是否有规律可循
  • 设计的 hash 函数在充分考虑了以上因素的状况下尽可能减小冲突。

3. 哈希冲突

​ 上面已经提到,不一样 key 经过 hash 函数产生相同的地址,即 H(key1) == H (key2),此时,key1 和 key2 就发生了 hash 冲突。

4. 哈希冲突的解决方案

​ 无论 hash 函数设计的如何巧妙,总会有特殊的 key 致使 hash 冲突, 特别是对童泰查找表来讲。

4.1. 开放定制法

​ 首先有一个H(key)的哈希函数。
若是H(key1)= H(keyi),那么 keyi 存储位置 Hi = (H(key)+di) MOD m。其中 m 是表长。

di 有三种取法:

  • 线性探测再散列: di = c * i。
  • 平方探测再散列: di = i * i。
  • 随机探测再散列:di 是 一个伪随机数。
4.2. 链地址法

​ 产生hash冲突后在存储数据后面加一个指针,指向后面冲突的数据。

image

4.3 公共溢出区法

​ 创建一个特殊存储空间,专门存放冲突的数据。此种方法适用于数据和冲突较少的状况。

4.4. 再散列法

​ 准备若干个hash函数,若是使用第一个hash函数发生了冲突,就使用第二个hash函数,第二个也冲突,使用第三个……

5. 哈希表的查找

5.1. 哈希表查找过程

​ 查找过程和造表过程一致,假设采用开放定址法处理冲突,则查找过程为:

  • 对于给定的 key,计算 hash 地址 index = H(key)。

  • 若是数组 arr[index] == null, 则查找不成功;

  • 若是数组 arr[index] == key,则查找成功;

  • 若是 (arr[index] != null && arr[index] != key),使用 hash 冲突解决方法求下一个地址,直到(arr[index] == null || arr[index] == key)。

5.2. 哈希表的查找效率

​ 决定 hash 表查找的 ASL 因素:

  • 选用的 hash 函数
  • 选用的处理冲突的方法
  • hash 表的饱和度, 装载因子 α = n/m (n 表示实际装载数据长度, m 为表长)

相关文章
相关标签/搜索