今天上午封装了一下哈希表,逻辑倒是不怎么复杂,主要是理论知识,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>哈希表</title>
</head>
<body>
<script>
function HashTable() {
this.storage = []
this.count = 0
this.limit = 8
function hashFunc(str,limit) {
var hashCode = 0;
for(var i = 0; i < str.length; i++) {
hashCode = 37 * hashCode + str.charCodeAt(i)
}
var index = hashCode % limit
return index
}
/* 错误取质数方法
function getPrime(num) {
var sqrtNum = Math.sqrt(num)
for(var i = 2; i <= sqrtNum; i++) {
while (num % i == 0) {
num++
}
}
}
*/
//正确取质数方法
function isPrime(num) {
var sqrtNum = parseInt(Math.sqrt(num))
for(var i = 2; i <= sqrtNum; i++) {
if(num % i == 0) {
return false
}
}
return true
}
function getPrime(num) {
while(!isPrime(num)) {
num++
}
return num
}
HashTable.prototype.put = function(key,value) {
var index = hashFunc(key,getPrime(this.limit))
var bucket = this.storage[index]
if(bucket == undefined) {
bucket = []
this.storage[index] = bucket
}
var isChange = false
for(var i = 0; i < bucket.length; i++) {
var tuple = bucket[i]
if(tuple[0] == key) {
tuple[1] = value
isChange = true
break
}
}
if(!isChange){
bucket.push([key,value])
this.count+=1
if(this.count >= this.limit * 0.75){
this.resize(getPrime(this.limit * 2))
}
}
}
HashTable.prototype.resize = function(newLimit) {
var oldStorage = this.storage
this.limit = newLimit
this.count = 0
this.storage = []
oldStorage.forEach(function(bucket) {
if(bucket == null) {
return
}
for(var i = 0; i < bucket.length; i++) {
var tuple = bucket[i]
this.put(tuple[0],tuple[1])
}
}).bind(this)
}
HashTable.prototype.get = function(key) {
var index = hashFunc(key,getPrime(this.limit))
var bucket = this.storage[index]
var hasFind = false
if(bucket == undefined) {
return false
}
for(var i = 0; i < bucket.length; i++) {
var tuple = bucket[i]
if(tuple[0] == key) {
hasFind = true
return tuple[1]
}
}
if(!hasFind) {
return false
}
}
HashTable.prototype.remove = function(key) {
var index = hashFunc(key,getPrime(this.limit))
var bucket = this.storage[index]
var isGet = this.get(key)
if(!isGet){
return false
}
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 primeNum = this.getPrime(Math.floor(this.limit / 2))
this.resize(primeNum)
}
break
}
}
}
HashTable.prototype.isEmpty = function() {
return this.count == 0
}
HashTable.prototype.size = function() {
return this.count
}
}
var ht = new HashTable()
ht.put('abc','123')
ht.put('cba','321')
ht.put('nba','521')
ht.put('mba','520')
console.log('ht',ht);
console.log('getAbc',ht.get('abc'));
console.log(ht.put('abc','111'));
console.log('getAbc',ht.get('abc'));
ht.remove('abc')
console.log('getAbc',ht.get('abc'));
console.log(ht.storage);
</script>
</body>
</html>
封装哈希表时出现的问题
1.在封装获取质数的时候出现了问题,已经在源码中标注自己第一次封装质数时的错误
代码逻辑,
2.在封装哈希函数的时候,想不明白为什么`霍纳法则(秦九韶算法)`为什么会被转换
成这样的算法,到现在也想不明白。
3.在封装resize方法时,遇到了一个this指向问题,forEach中的this指向问题,看
老师笔记才明白用forEach数组循环,为什么要加bind方法改变this指向,本以为会和
react里面一样也可以用箭头函数轻松解决this指向问题,我天真了,用箭头函数
去打印this,发现this指向还是window.
4.封装remove方法的时候,少考虑当数量足够小的时候,需要降低哈希表的容量了。