一、哈希表基于数组实现
- 提供快速的插入-删除-查找操作
- 插入和删除的时间接近O(1)的时间级
- 哈希表的速度比树还要快,基本可以瞬间找到想要的元素
- 哈希表相对于树来说编码要容易
二、 哈希表相对于数组的一些不足
- 哈希表中的数据是无序的,所以不能以某种方式来遍历的元素
- 哈希表中key是不允许重复的
三、哈希表的一些概念
-
哈希化:将大数字转化成数组范围内下标的过程
-
哈希函数:通常我们会将单词转成大数字,大数字在进行哈希化的代码实现放在一个函数里
-
哈希表:最终将数据插入到的这个数组,对整个结构的封装,称为哈希表
-
哈希冲突:通过哈希函数得到的下标值发生重复,有两种方法解决(链地址法、开放地址法)
-
链地址法(拉链法)
- 链地址解决冲突的办法是每个数组单位不仔存储单个数据,而是一个链条
- 链条的数据结构可以是数组或者链表
-
开放地址法
-
主要工作方式是寻找空白的单元格来添加重复的数据
-
探索新的位置有三种方法:
- 线性探测
- 二次探测
- 再哈希法
-
哈希化效率对比
- 链地址法比开放地址法的效率要好一点
- 在真实开发中,使用链地址法较多
-
四、优秀的哈希函数
- 快速的计算:减少乘除
- 霍纳法则:可以减少乘的次数,减少时间复杂度
- 均匀的分布:减少重复
- 在使用常量的地方,尽量使用质数,比如在哈希表的长度、N次幂的底数、再哈希法中的常量
五、哈希函数的实现
//将字符串转成比较大的数字:hashCode
//将比较大的数字hashCode压缩到数组范围(大小)之内
function hashFunc(str,size){
var hashCode = 0;
//霍纳法则
for(var i = 0 ;i<str.length;i++){
hashCode = 37*hashCode+str.charCodeAt(i) //获取unicode编码
}
//取余
var index = hashCode % size;
return index;
}
- 创建哈希表
//封装哈希表类
function HashTable(){
//哈希表属性
this.storage = [];
this.count = 0; //计算装载因子,通过装载因子来进行减容或者扩容
this.limit = 7 //数组的大小
//哈希表方法
//1.哈希函数
HashTable.prototype.hashFunc = function (str,size){
var hashCode = 0;
//霍纳法则
for(var i = 0 ;i<str.length;i++){
hashCode = 37*hashCode