散列表也被稱爲哈希表,Hash表是一種特殊的數據結構。數組
散列後的數據 能夠快速插入和取用bash
在散列表上插入、刪除和取用數據很是快,可是查找數據卻效率低下數據結構
js散列表基於數組設計,理想狀況散列函數會將每個鍵值映射爲惟一的數組索引,數組長度有限制,更現實的策略是將鍵均勻分佈函數
數組長度是預先設定的,能夠隨時增長,全部元素根據和該元素對應的鍵,保存數組特定的位置this
即便使用高效的散列函數,依然存在兩個鍵值相同的狀況,這種現象稱爲碰撞(collision)spa
數組的長度應該是一個質數,全部的策略都基於碰撞設計
開鏈法:兩個鍵相同保存位置同樣,開闢第二數組,也稱第二個數組爲鏈,適合空間小,數據量大code
線性探測法屬於開放尋址散列,查找散列位置若是當前位置沒有繼續尋找下一個位置。存儲數據較大較適合。數組大小>=1.5*數據(開鏈法),數組大小>=2*數據(線性探測法)索引
/** * 一個簡單的散列表 * @constructor */ function HashTable() { this.table = new Array(137); // 定義數組長度 this.simpleHash = simpleHash; // 簡單的散列函數 this.betterHash = betterHash; // 簡單的散列函數 this.showDistro = showDistro; // 顯示元素 this.put = put; // 插入元素 this.openPut = openPut; // 開鏈法插入元素 this.linkPut = linkPut; // 線性探測法插入元素 this.get = get; // 獲取元素 this.bulidTable = bulidTable //添加二維數組 } //簡單的散列函數 除留餘數法 function simpleHash(data) { var total = 0 for(var i = 0; i < data.length; i++){ total += data.charCodeAt(i) } console.log(data + '->total' + total) return total % this.table.length } //顯示元素 function showDistro() { for(var i = 0; i < this.table.length; i++) { if(this.table[i] !== undefined) { console.log('鍵值是->' + i + '值是' + this.table[i]) } } } //插入元素 function put(data) { var pos = this.simpleHash(data) this.table[pos] = data } //獲取元素 function get(data) { return this.table[this.simpleHash(data)] } var ht = new HashTable() ht.put('abc') ht.put('china') ht.put('bbb') ht.put('ss') ht.put('nicah') ht.put('cba') ht.showDistro()
能夠看到咱們插入6個值,最後只顯示3個,緣由是發生了碰撞get
//改造後的散列函數 function betterHash(data) { var h = 31 var total = 0 for(var i = 0; i < data.length; i++){ total += h*total + data.charCodeAt(i) } console.log(data + '->total' + total) return total % this.table.length } //更改put function put(data) { var pos = this.betterHash(data) //使用betterHash this.table[pos] = data }
能夠看到其餘元素能夠顯示出來了,可是添加相同元素的時候,不顯示
在建立存儲散列過的鍵值數組時,建立一個新的空數組,而後將該數組付給散列表中的每一個數組元素,這樣建立了一個二維數組,也稱第二個數組爲鏈。
//添加二維數組 function bulidTable() { for(var i = 0; i<this.table.length; i++){ this.table[i] = new Array() } }//開鏈法插入元素 function openPut(data) { var pos = this.simpleHash(data) var index = 0 if(this.table[pos][index] === undefined) { this.table[pos][index] = data index ++ }else { while(this.table[pos][index] !== undefined) { ++index } this.table[pos][index] = data } } //顯示元素更改 function showDistro() { for(var i = 0; i < this.table.length; i++) { if(this.table[i][0] !== undefined) { console.log('鍵值是->' + i + '值是' + this.table[i]) } } } //插入元素更改成simpleHash function put(data) { var pos = this.simpleHash(data) this.table[pos] = data } var ht = new HashTable() ht.bulidTable() ht.openPut('abc') ht.openPut('china') ht.openPut('bbb') ht.openPut('ss') ht.openPut('nicah') ht.openPut('cba') ht.openPut('cba') ht.showDistro()
能夠看到全部元素都被顯示出來了
當發生碰撞時,檢測下一個位置是否爲空。若是爲空,就將此數據存入該位置;若是不爲空,則繼續檢查下一個位置,直到找到下一個空的位置爲止。
//線性探測法 function linkPut(data) { var pos = this.simpleHash(data) if(this.table[pos] === undefined) { this.table[pos] = data }else { while(this.table[pos] !== undefined) { pos++ } this.table[pos] = data } } //顯示元素 function showDistro() { for(var i = 0; i < this.table.length; i++) { if(this.table[i] !== undefined) { console.log('鍵值是->' + i + '值是' + this.table[i]) } } } var ht = new HashTable() // ht.bulidTable() ht.linkPut('abc') ht.linkPut('china') ht.linkPut('bbb') ht.linkPut('ss') ht.linkPut('nicah') ht.linkPut('cba') ht.linkPut('cba') ht.showDistro()
能夠看到全部元素都被顯示出來了
至此,算是完成了散列表