zoukankan      html  css  js  c++  java
  • 哈希表结构_哈希表的扩容

    哈希表的扩容

      1. 为什么要扩容

                    1. 扩容即是将哈希表的长度增加,通常是变为原来的两倍

                    2. 使用链地址法封装哈希表时, 填装因子(loaderFactor)会大于1, 理论上这种封装的哈希表时可以无限插入数据的

                    3. 但是但是随着数据量的增多,哈希表中的每个元素会变得越来越长, 这是效率会大大降低

                    4. 因此, 需要通过扩容来提高效率

      2. 如何扩容

                    1. 扩容就是将哈希表的存储空间增加为原来的两倍

                    2. 此时,需要将所有数据项都进行修改(需要重新调用哈希函数,来获取新的位置)

                 3. 哈希表扩容是一个比较耗时的过程,但是功在当代, 利在千秋

      3. 什么情况下扩容

                    常见的情况是在填装因子(loaderFactor) > 0.75是进行扩容

     

      4. 扩容的代码实现

                    1. 拷贝之前封装的哈希表代码

                    2. 在哈希表中增加变容(resize)方法

      5. 哈希表扩容的代码实现

        function hashMap(){
            // 哈希表的属性
            this.storage = [];
            this.count = 0;
            this.limit = 8;
    
            // 封装哈希函数类
            hashMap.prototype.hashFun = function(str, size = 7){
                // 1. 定义hashCode变量
                var hashCode = 0;
    
                // 2. 霍纳算法,计算hashCode的值
                for(var i = 0; i < str.length; i++){
                    // 这里的常数值37是常用质数值
                    hashCode = 37 * hashCode + str.charCodeAt(i);
                }
    
                // 3. 取余操作
                var index = hashCode % size;
    
                return index;
            }
    
            // a. 向哈希表中插入数据
            hashMap.prototype.put = function(key, value){
                // 1. 将要插入的键转换成哈希码
                var index = this.hashFun(key, this.limit);
    
                // 2. 根据索引值,取出storage中对应的bucket
                var bucket = this.storage[index];
    
                // 3. 若取出的bucket为空
                if(bucket == undefined){
                    // 为空,则创建一个数组,并将新增的数据以数组的形式存入数组
                    bucket= [[key, value]];
                    this.storage[index] = bucket;
                    return true;
                }
                
                // 4 若取出的bucket为重复数据, 则修改value值,并返回true;
                for(var i = 0; i < bucket.length; i++){
                    if(bucket[i][0] == key){
                        bucket[i][1] = value;
                        return true;
                    }
                }
    
                // 5. 若不为重复数据,则添加key和value,并返回true;
                bucket.push([key, value]);
                this.count += 1;
                return true
    
                // 6. 判断是否需要扩容
                
                
            }
    
            // b. 在哈希表中查找数据 
            hashMap.prototype.get = function(key){
                // 首先计算输入key值的哈希码
                var index = this.hashFun(key, this.limit);
    
                // 取出哈希码对应的那个bucket
                var bucket = this.storage[index];
                if(bucket == undefined){
                    return null;
                }
    
                // 依次遍历这个bucket
                for(var k = 0; k < bucket.length; k++){
                    if(bucket[k][0] == key){
                        return bucket[k][1];
                    }
                }
    
                // 若没有找到这个key值,返回null
                return null;
            }
    
            // c. 从哈希表中删除元素
            hashMap.prototype.remove = function(key){
                // 首先计算输入key值的哈希码
                var index = this.hashFun(key, this.limit);
    
                // 根据哈希码.取出对应的bucket
                var bucket = this.storage[index];
    
                // 依次查找bucket中的元素
                for(var i =0; i < bucket.length; i++){
                    if(bucket[i][0] == key){
                        bucket.splice(i, 1);
                        this.count -=1;
                        return true;
                    }
                }
    
                return false;
            }
    
            // d. 判断哈希表是否为空
            hashMap.prototype.isEmpet = function(){
                return count == 0;
            }
    
            // e. 查看哈希表中的数据个数
            hashMap.prototype.size = function(){
                return this.count;
            }
    
            // f. 统计哈希表中存储的数据的分布情况
            hashMap.prototype.sta = function(){
                var sta = [];
                for(var s = 0; s < this.storage.length; s++){
                    if(this.storage[s] == undefined){
                        sta.push(0);
                    }else{
                        sta.push(this.storage[s].length);
                    }
                }
                return sta
            }
    
            // g. 扩/缩容方法
            hashMap.prototype.resize = function(newLimit){
                // 1. 首先保存已保存在原哈希表中的数据
                var oldStorage = this.storage;
    
                // 2. 新哈希表的方法
                this.storage = [];
                this.count = 0;
                this.limit = newLimit;
                
                // 3. 扩容/缩容操作
                for(var j = 0; j < oldStorage.length; j++){
                    // 1. 取出原哈希表的每个元素链
                    var bucket = oldStorage[j];
                    for(var k = 0; k < bucket.length; k++){
                        // 2. 取出每个元素链内的元素 即每组数据为: key = bucket[k][0], value = bucket[k][1]
                        var index = this.hashFun(bucket[k][0], this.limit);
                        
                        // 3. 将元素依次放入新的哈希表中
                        // 3.1 判断新哈希表中的元素链是否为空
                        if(this.storage[index] == undefined){
                            // 为空,则直接放入
                            this.storage[index] = [bucket[k]];
                            break;
                        }else{
                            // 不为空,则添加在末尾
                            this.storage[index].push(bucket[k]);
                        }
    
                        // 3. 将元素依次放入新的哈希表中
                        // 这一步也可以调用自身的put方法
                        // this.put(bucket[k][0], bucket[k][1]);
                    }
                }
    
            }
        }
    View Code
  • 相关阅读:
    1.33 (累积互素数)
    1.33 (过滤累积和 求区间内所有素数之和)
    1.32 (更高层次的抽象! 乘法与加法本来就是一回事)
    1.31 (另一种求圆周率的算法)
    1.30 (递归的sum变迭代)
    习题1.29 (积分方法的优化---simpson规则)
    1.3.1 (对过程的抽象)
    SICP习题 1.23(素数查找的去偶数优化)
    SICP习题 1.22(素数)
    pom.xml
  • 原文地址:https://www.cnblogs.com/carreyBlog/p/13657099.html
Copyright © 2011-2022 走看看