1. 哈希思想
哈希表 hash table 也称散列表, 是由数组演化而来, 底层依赖 数组 支持按照下标快速 访问元素的特性;
1.1 hash 原理
哈希表利用的是 数组按照下标访问元素时, 其时间复杂度为 O(1) 这样的特性;
实际操作时: 通过哈希函数, 将元素的键值映射为下标, 然后, 将对应的数据存储在 数组中 对应的下标的位置;
当按照键值 查询元素时, 使用同样的哈希函数, 将键值转化为 数组下标, 从数组中 这个下标对应的位置取数据。
作用, 可以快速 访问表中的某个 元素, 时间复杂度O(1);
1.2 hash 举例
例如:
以数组举例 :
数组中 索引下标 可当做 成 hash 表中的 key;
数组中 索引所对应的数值 可看成 hash 表中 的 值;
以python 中的 字典举例: dict()
字典中的 关键字 可作为 hash 表中的 key;
字典中 关键字所对应的 内容 作为 hash 表中的 值;
2. 哈希函数
2.1. hash(key)
hash(key): key 表示元素的 键值;
hash(key) 的值 表示经过 哈希函数 计算得到的 哈希值;
2.2 哈希函数的3个基本要求
- 哈希函数计算得到的哈希值 是一个 非负整数;
if key1 == key2 , then hash(key1) == hash(key2)
if key1 != key2 , then hash(key1) != hash(key2)
3. 哈希冲突
哈希冲突: 不同的键 经过 同一个哈希函数, 输出的值 映射到同一个 哈希值 上 ;
常用的解决方法: 开放寻址法 和 链表法
3.1. 开放寻址法
一旦出现哈希冲突, 通过重新 探测新位置的方法 解决冲突;
最简单有, 线性探测法:
当向哈希表插入数据时, 如果某个数据经过哈希函数计算后, 对应的存储位置已经被占用了, 则从这个位置开始, 在数组中依次往后查找, 直到找到控线位置为止;
在此基础上,还有 二次探测法, 双重哈希法;
3.2. 链表法
在发生冲突的那些位置, 建立“桶” 或者称 “ 槽”, 即在冲突的位置上 后面接入一个链表;
这样冲突的哈希值, 接着那个位置的 链表中继续存放;
当 N : 表示 哈希表中 元素的个数;
M: 表示 哈希表中 槽的 个数;
则 N / M = K, k 称为装载因子;
装载因子越大, 说明链表长度越长, 哈希表的性能就会越低;