js封装一个哈希表

Posted 正经的流刺源

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js封装一个哈希表相关的知识,希望对你有一定的参考价值。

// 基于数组封装一个哈希表
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());

 

以上是关于js封装一个哈希表的主要内容,如果未能解决你的问题,请参考以下文章

HashMap原理:哈希函数的设计

STL详解(十三)—— 用一个哈希表同时封装出unordered_map和unordered_set

回归 | js实用代码片段的封装与总结(持续更新中...)

手撕STLunordered_setunordered_map(用哈希表封装)

unordered_mapunordered_set模拟实现

unordered_mapunordered_set模拟实现