1. 程式人生 > 實用技巧 >雜湊表結構_雜湊表的擴容

雜湊表結構_雜湊表的擴容

雜湊表的擴容

  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