哈希表介绍
哈希表是一种非常重要的数据结构, 几乎所有的编程语言都有直接或者间接的应用这种数据结构.
- 哈希表通常是基于数组进行实现的, 但是相对于数组, 它也很多的优势:
- 它可以提供非常快速的插入-删除-查找操作
- 无论多少数据, 插入和删除值需要接近常量的时间: 即O(1)的时间级. 实际上, 只需要几个机器指令即可
- 哈希表的速度比树还要快, 基本可以瞬间查找到想要的元素
- 哈希表相对于树来说编码要容易很多.
- 哈希表相对于数组的一些不足:
- 哈希表中的数据是没有顺序的, 所以不能以一种固定的方式(比如从小到大)来遍历其中的元素.
- 通常情况下, 哈希表中的key是不允许重复的, 不能放置相同的key, 用于保存不同的元素.
- 那么, 哈希表到底是什么呢?
- 似乎还是没有说它到底是什么.
- 这也是哈希表不好理解的地方, 不像数组和链表, 甚至是树一样直接画出你就知道它的结构, 甚至是原理了.
- 它的结构就是数组, 但是它神奇的地方在于对下标值的一种变换, 这种变换我们可以称之为哈希函数, 通过哈希函数可以获取到HashCode.
- 不着急, 我们慢慢来认识它到底是什么.
- 体会哈希表
- 案例一: 公司使用一种数据结构来保存所有员工
- 案例介绍:
- 假如一家公司有1000个员工, 现在我们需要将这些员工的信息使用某种数据结构来保存起来
- 你会采用什么数据结构呢?
- 方案一: 数组
- 一种方案是按照顺序将所有的员工依次存入一个长度为1000的数组中. 每个员工的信息都保存在数组的某个位置上.
- 但是我们要查看某个具体员工的信息怎么办呢? 一个个找吗? 不太好找.
- 数组最大的优势是什么? 通过下标值去获取信息.
- 所以为了可以通过数组快速定位到某个员工, 最好给员工信息中添加一个员工编号, 而编号对应的就是员工的下标值.
- 当查找某个员工的信息时, 通过员工编号可以快速定位到员工的信息位置.
- 方案二: 链表
- 链表对应插入和删除数据有一定的优势.
- 但是对于获取员工的信息, 每次都必须从头遍历到尾, 这种方式显然不是特别适合我们这里.
- 最终方案:
- 这样看最终方案似乎就是数组了. 但是数组还是有缺点, 什么缺点呢?
- 假如我想查看一下张三这位员工的信息, 但是我不知道张三的员工编号, 你怎么办呢?
- 当然, 你说我可以问他. 但是你每查找一个员工都是问一下这个员工的编号吗? 不合适.
- 能不能有一种办法, 让张三的名字和它的员工编号产生直接的关系呢?
- 也就是通过张三这个名字, 我就能获取到它的索引值, 而再通过索引值我就能获取到张三的信息呢?
- 这样的方案已经存在了, 就是使用哈希函数, 让某个key的信息和索引值对应起来.
- 案例介绍:
线性探测
-
下面的等式显示了线性探测时,探测序列(P)和填装因子(L)的关系
- 对成功的查找: P = (1+1/(1-L))/2
- 对不成功的查找: P=(1+1/(1-L)^2)/2
-
公式来自于Knuth(算法分析领域的专家, 现代计算机的先驱人物), 这些公式的推导自己去看了一下, 确实有些繁琐, 这里不再给出推导过程, 仅仅说明它的效率.