一.哈希表扩容
HashTable.prototype.resize = function(newLimit){
// 1.保存旧的数组内容
var oldStorage = this.storage
// 2.重置所有的属性
this.storage = []
this.count = 0
this.limit = newLimit
// 3.遍历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])
}
}
}
- 怎样判断是否需要扩容操作:
if(this.count > this.limit * 0.75)
就可以实行扩容操作
this.resize(this.limit * 2)
哈希表扩大一倍 - 如何进行缩容操作
if(this.limit > 7 && this.count < this.limit * 0.25)
就可以实行缩容操作
this.resize(Math.floor(this.limit / 2))
哈希表缩容一倍
二.容量质数
在哈希表中容量最好为质数(质数是指只能被1和自己整除的数)
这里先说一个简单的面试题,判断一个数是否为质数
- 普通判断质数算法
function isPrime(num){
for(var i = 2; i < num; i++){
if(num % i == 0){
return false
}
return true
}
}
但是普通的判断素数法效率不高,对于每个数n其实不需要从2判断到n-1,一个数如果能被分解,那么分解到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n)。例如16可以被分解为28,也可以被分解为44,所以其实只需要遍历到sqrt(n)即可。
- 高效判断质数算法
function isPrime(num){
// 1.获取num的平方根
var temp = parseInt(Math.sqrt(num))
// 2.循环判断
for(var i = 2; i <= temp; i++){
if(num % i == 0){
return false
}
return true
}
}
三.实现哈希表中容量恒为质数
若在添加数据之后,要判断哈希表是否需要扩容操作
if(this.count > this.limit * 0.75){
var newSize = this.limit * 2
var newPrime = this.getPrime(newSize)
this.resize(newPrime)
}
若在删除数据之后,要判断哈希表是否需要缩容操作
if(this.limit > 7 && this.count < this.limit * 0.25){
var newSize = Math.floor(this.limit / 2)
var newPrime = this.getPrime(newSize)
this.resize(newPrime)
}
容量恒为质数操作
HashTable.prototype.isPrime = function(num){
// 1.获取num的平方根
var temp = parseInt(Math.sqrt(num))
// 2.循环判断
for(var i = 2; i <= temp; i++){
if(num % i == 0){
return false
}
return true
}
}
HashTable.prototype.getPrime = function(num){
while(!this.isPrime(num)){
num++
}
return num
}