哈希表結構_哈希表的擴容


哈希表的擴容

  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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM