// 基于数组封装一个哈希表 function HashTable() { // 属性 this.storage = []; this.count = 0; // 数据的存储量 this.limit = 7; // 容量长度最好为质数,利于数据在容器中均匀分布 // -----------------方法------------ // 哈希函数 HashTable.prototype.hashFunc = function (str,size) { // 定义一个hashCode let hashCode = 0; // 霍纳算法 计算尽可能多加减,少乘除,提高运算效率 for (var i = 0; i < str.length; i++) { hashCode = hashCode * 37 + str.charCodeAt(i) } // 范围压缩 求余获得位置下标 let index = hashCode % size; return index } // 新增&修改 HashTable.prototype.put = function(key,value){ // 1.通过哈希函数获取到存储位置的下标 let index = this.hashFunc(key,this.limit); // 2.判断这个位置是否有存储内容 this.storage[index] = this.storage[index] == null ? [] : this.storage[index]; // 3.判断是修改还是新增 for(let i = 0;i < this.storage[index].length;i++){ // 修改 if(this.storage[index][i][0] === key){ this.storage[index][i][1] = value; return } } // 新增 this.storage[index].push([key,value]); // 4.存储数量+1 this.count++; // 5.判断是否需要扩容 if(this.count > this.limit * 0.75){ this.resize(this.getPrime(this.limit * 2)) } } // 获取 HashTable.prototype.get = function(key){ // 1.通过哈希函数获取到位置下标 let index = this.hashFunc(key,this.limit); // 2.判断此位置处是否为空 let bucket = this.storage[index]; if(bucket == null) return null; // 3.线性查找此位置中存储的数据 for(let i = 0; i < bucket.length;i++){ // 找到返回数据 if(bucket[i][0] === key){ return bucket[i][1] } } // 没找到返回null return null } // 删除 HashTable.prototype.remove = function(key){ // 1.通过哈希函数获取到index let index = this.hashFunc(key,this.limit); // 2.判断此位置是否为null let bucket = this.storage[index]; if(bucket == null) return null; // 3.遍历找对应的数据 for(let i = 0; i < bucket.length;i++){ let tuple = bucket[i]; // 找到删除此数据 if(tuple[0] === key){ bucket.splice(i,1); // 存储数量-1 this.count--; // 4.判断是否需要缩容 if(this.limit > 7 && this.count < this.limit * 0.25){ this.resize(this.getPrime(Math.floor(this.limit / 2))) } return tuple[1] } } // 没找到返回null return null } // 哈希表是否为空 HashTable.prototype.isEmpty = function(){ return this.count == 0 } // 哈希表中存储元素的个数 HashTable.prototype.size = function(){ return this.count } // 哈希表扩容&缩容 HashTable.prototype.resize = function(newlimit){ // 1.用oldStorage承载之前的数据 let oldStorage = this.storage; // 2.重置storage this.storage = []; this.limit = newlimit; this.count = 0; // 3.遍历 将之前的数据重新存储到新的storage中 for(var i = 0; i < oldStorage.length; i++){ let bucket = oldStorage[i]; if(bucket == null) continue; for(var j = 0; j < bucket.length; j++){ let tuple = bucket[j]; this.put(tuple[0],tuple[1]) } } } // 判断是否是质数 HashTable.prototype.isPrime = function(num){ let temp = parseInt(Math.sqrt(num)); 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 } } // 测试 let hash = new HashTable(); hash.put('1',{name: 'lili',age:12}) hash.put('tom',{age:19,id:1234}) hash.put('mariy',{age:11,sex:'女'}) console.log(hash); // console.log(hash.get('1')); // console.log(hash.remove('1')); // console.log(hash.get('1')); // console.log(hash.isEmpty()); // console.log(hash.size()); // hash.put('a',11) // hash.put('b',21) // hash.put('c',31) // hash.put('d',41) // hash.put('e',51) // console.log(hash); // console.log(hash.size());