1,哈希表的基本概念
- 散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。
- 哈希函数:也称为是散列函数,是Hash表的映射函数,它可以把任意长度的输入变换成固定长度的输出,该输出就是哈希值。哈希函数能使对一个数据序列的访问过程变得更加迅速有效,通过哈希函数,数据元素能够被很快的进行定位。
- 解决冲突的办法:1:链地址法,2:开放地址法
2,哈希表的结构

3,哈希表的实现
class HashTable{
//属性
constructor(){
this.storage=[]//作为数组,存放元素
this.count=0//用于记录HashTable存放的数量
this.limit=7//表示数组当前的常数
}
//Hash函数
hashFunc(str,size){
/*1,将字符串转换成比较大的数字:hashCode,2,将数字大的hashCode压缩到数组的(大小)范围内,size:代表传入的字符串,size:代表数组的大小*/
//1,定义hashCode的变量
var hashCode=0
//2,霍纳算法,来计算hashCode的值
for(var i=0;i<str.length;i++){
hashCode=37*hashCode+str.charCodeAt(i)
}
//3,取余操作
var index=hashCode % size
return index
}
//hashTable的插入和修改
/*
1,根据key获取索引值,目的:将数据插入到对应的位置
2,根据索引值取出bucket,如果bucket(桶)不在,创建bucket(桶)
3,判断是新增,还是修改,如果有只,那么修改,没有就是新增
*/
put(key,value){
//1,根据key获取相对应的index
var index=this.hashFunc(key,this.limit)
//2,根据index取出相对应的bucket,bucket是一个数组
var bucket=this.storage[index]
//判断bucket是否存在
if(bucket==null){
bucket=[]
this.storage[index]=bucket
}
//4,判断是否为修改数据
for(var i=0;i<bucket.length;i++){
var tuple=bucket[i]
if(tuple[0]==key){
tuple[1]=value
return
}
}
//5,进行添加操作
bucket.push([key,value])
this.count+=1
//判断是否需要扩容
if(this.count>this.limit*0.75){
var newPrime=this.getPrime(this.limit*2)
this.resize(newPrime)
}
}
//获取操作
/*
1,根据key获取相对应的index
2,根据index获取相对应的bucket
3,判断bucket是否为null,如果为null,直接返回null
4,线性查找bucket中的每一个key是否等于传入的key,如果等于直接返回value
5,遍历后,依然没有找到相对应的key,直接返回null
*/
get(key){
//根据Key获取相对应的index
var index=this.hashFunc(key,this.limit)
//根据index获取相对应的bucket
var bucket=this.storage[index]
//判断bucket是否存在
if(bucket==null){
return null
}
for(var i=0;i<bucket.length;i++){
var tuple=bucket[i]
if(tuple[0]==key){
return tuple[1]
}
}
//依然没有找到
return null
}
//删除操作
/*
1,根据key获取相对应的index
2,根据index获取相对应的bucket
3,判断bucket是否为null,如果不存在,直接返回null
4,线性查找bucket,寻找相对应的key,并且删除
5,依然没有找到那么返回null
*/
remove(key){
//根据key获取相对应的index
var index=this.hashFunc(key,this.limit)
//根据index获取相对应的bucket
var bucket=this.storage[index]
//判断bucket是否存在
if(bucket==null){
return null
}
//有bucket,那么进行线性查找,并且删除
for(var i=0;i<bucket.length;i++){
var tuple=bucket[i]
if(tuple[0]==key){
bucket.splice(i,1)
this.count-=1
//缩小容量
if(this.limit>7 && this.count<this.limit*0.25){
var newPrime=this.getPrime(Math.floor(this.limit/2))//用Math.floor确保为整数
this.resize(newPrime)
}
return tuple[1]
}
}
//5,遍历后没有找到
return null
}
//判断HashTable是否为空
isEmpty(){
return this.count==0
}
//获取HashTable元素的个数
size(){
return this.count
}
//HashTable的扩容
resize(newLimit){
//1,保存旧的数组
var oldStorage=this.storage
//重置所有属性
this.storage=[]
this.count=0
this.limit=0
//遍历获取oldStorage所有的bucket
for(var i=0;i<oldStorage.length;i++){
//3.1取出相对应的bucket
var bucket=oldStorage[i]
//3.2判断bucket是否为空
if(bucket==null){
continue
}
//3.3,bucket中有数据,取出数据重新插入
for(var j=0;j<bucket.length;j++){
var tuple=bucket[j]
this.put(tuple[0],tuple[1])
}
}
}
//判断数字是否为质数
isPrime(num){
var temp=parseInt(Math.sqrt(num))
for(var i=2;i<=temp;i++){
if(num % 2==0){
return false
}
}
return true
}
//如果不是质数让其自增,得到质数
getPrime(num){
while(!this.isPrime(num)){
num++
}
return num//这个数为质数
}
}
//创建HashTable
var ht=new HashTable()
ht.put('one','1')
ht.put('two','2')
ht.put('three','3')
ht.put('four','4')
ht.put('five','5')
ht.put('six',6)
ht.put('seven','7')
console.log(ht)