散列表/Hash表

  • 參考書:《學習JavaScript數據結構與算法》
  • GitHub demo:https://github.com/nebulium/HashTable
  • 相比於「字典」來講,HASH表實際上也是經過名/值對進行存儲。可是存儲的數據結構有所不一樣。待存儲的信息的「名(key)」經過特定的處理(散列函數)映射成數字。這些數字做爲數組的索引指向一個數組的某個位置,而信息的「值(value)」就存儲在數組的這個位置上。
  • 散列表的原理是比較簡單的,但設計散列表的時候須要注意:散列函數、衝突的解決。其中散列函數決定了key映射成數字致使的存儲效率以及衝突的多寡;而「衝突」在不一樣key映射成同一個數字、指向同一個位置的時候出現,根據《學習JavaScript數據結構與算法》一書指出,解決衝突有:分離連接、線性探查和雙散列法。
  • 因爲只是爲了對必要的算法和結構的基本原理有所瞭解,因此徹底按照參考書進行實現:

a.  loseloseHash.js: 不考慮衝突的散列表+「lose lose」散列函數git

b. djb2Hash.js: 不考慮衝突的散列表+djb2散列函數 github

c. linkedHash.js: 分離連接解決衝突的散列表+「lose lose」散列函數 算法

d. linearHash.js: 線性探查的散列表+「lose lose」散列函數 數組

 

loseloseHash.js

  • function loseloseHashCode(key): key映射成數值,用ascii碼的轉換進行處理,藉助key.charCodeAt(i)方法。
  • put(key,value)
  • remove(key)
  • get(key)

 

djb2Hash.js

  • put/remove/get方法沒有變。
  • function djb2Hash(key):一樣是利用key的每一個字母的ascii碼進行處理,不過hash的初值、每次線性相乘的參數、以及最後取餘操做的基數發生了改變。這些參數是通過研究的可使散列表效率更高的數值。

 

linkedHash.js

  • 解決衝突的最簡單的方法,使散列表的每個位置(數組的每個位置)成爲一個鏈表,這樣當產生衝突的時候,就能夠以鏈表的形式在同一個位置存儲不一樣key的值了。可是顯然,這個key也須要封裝在鏈表的元素之中,以區分同一個位置(同一個索引)對應的不一樣信息。
  • 這種方法顯然須要額外的空間(數組之外的鏈表空間)
  • 利用新加的輔助類表示要加入LinkedHash的實例,用以進行上面提到過的區分行爲:
    function ValuePair(key,value){
        this.key = key;
        this.value = value;
    
        this.toString = function(){
            return '['+this.key+'-'+this.value+']'; //方便進行觀察
        }
    }
  • 須要重寫put、get、remove這三個方法。利用鏈表的知識進行重寫,而且把每個元素都對ValuePair實例化進行存儲。原理較爲簡單。
  • 注意remove(key)方法,注意鏈表構造函數的remove()方法。
  • 用到兩個輔助的構造函數:鏈表構造函數以及ValuePair的構造函數。這兩個函數徹底能夠放在HashTable構造函數以外實現。由於HashTable內部在實例化鏈表的時候會在全局環境中找須要的構造函數,且這兩個構造函數不須要用到HashTable中的值,即兩者是相對獨立的。可是爲了保證這個數據結構的完整性,將這兩個構造函數都放在hash表的構造函數中當作私有函數。

linearHash.js 線性探查。

  • 這種衝突的解決方法,在向表中添加一個新的元素的時候,若是索引爲index的位置已經被佔據了,則嘗試index+1的位置,若是index+1的也被佔據了,則放在index+2的位置,以此類推。
  • 一樣須要重寫put/get/remove,主要是有一個查找的過程。
  • 一樣須要用ValuePair的實例來表示值。
  • 移除以及查找的算法顯然有不足,但這個不足依賴於插入算法彌補。不是完美的方法。
相關文章
相關標籤/搜索