散列表的介紹
散列算法的作用是儘可能快地在數據結果中找到一個值,通常在數據結果中獲得一個值(get方法),需要遍歷整個數據結構來找到它。如果使用散列函數,就知道值的具體位置,因此能夠快速檢索到該值。散列函數的作用是給定一個鍵值,然後返回值在表中的地址。
現實實例,就如email記錄本。鍵名就如用戶名,值爲email,然後當我們每保存一條數據的時候。通過鍵名用ASCII來轉換成散列函數。如下圖:
散列圖算法詳講
首先我們通過添加3條數據,來生成一個散列圖:
var hash = new HashTable();
hash.put('Gandalf', '[email protected]');
hash.put('John', '[email protected]');
hash.put('Tyrion', '[email protected]');
三條數據生成的hash函數:
19-Gandalf
29-John
16-Tyrion
hashTable類在本文最底部。
下圖顯示整個操作流程:
成功生成一個散列圖後,我們對他進行一些操作看看:
hash.get('Gandalf')//[email protected]
hash.remove('Gandalf');
hash.get('Gandalf')//undefined
散列函數方法
散列函數算法有很多種,給大家認識的有“lose lose”散列函數,還有djb2散列函數。因爲計算散列函數的時候,有可能2個不一樣的值算出一樣的值,這樣導致散列表產生衝突。因此爲樂避免衝突,我們需要優化散列方法也就是djb2散列函數。
var loseloseHashCode = function (key) {
var hash = 0;
for (var i = 0; i < key.length; i++) {
hash += key.charCodeAt(i);
}
return hash % 37;
};
var djb2HashCode = function (key) {
var hash = 5381;
for (var i = 0; i < key.length; i++) {
hash = hash * 33 + key.charCodeAt(i);
}
return hash % 1013;
};
djb2數發爲,初始一個hash值爲5381(大多數推薦使用這值),然後送代參數key,將hash與33相乘(用來當作一個魔力數),並和當前送代到的字符ASCII瑪相加。最後我們將使用相加的和與另一個隨機質數相除得餘數。
用上面3條數據再試一下:
//loselose算法:
19-Gandalf
29-John
16-Tyrion
//djb2算法:
798-Gandalf
838-John
624-Tyrion
這裏我通過修改hash函數的算法來減少衝突,但其他還有其他辦法可以減少衝突,如分離鏈接和線性探索等。有興趣的朋友可以搜索一下學習下。
ES6散列表完整實現代碼:
let HashTable = (function(){
const table = [];
class HashTable {
constructor () {
}
loseloseHashCode(key) {//獲取hash函數loselose算法
var hash = 0;
for (var i = 0; i < key.length; i++) {
hash += key.charCodeAt(i);
}
return hash % 37;
}
djb2HashCode(key) {//獲取hash函數djb2算法
var hash = 5381;
for (var i = 0; i < key.length; i++) {
hash = hash * 33 + key.charCodeAt(i);
}
return hash % 1013;
}
hashCode(key) {//獲取散列函數
return this.loseloseHashCode(key);
}
put(key, value) {//插入數據
var position = this.hashCode(key);
console.log(position + ' - ' + key);
table[position] = value;
}
get(key) {//返回特定值
return table[this.hashCode(key)];
}
remove(key){//刪除特定元素
table[this.hashCode(key)] = undefined;
}
print() {//輸出散列表
for (var i = 0; i < table.length; ++i) {
if (table[i] !== undefined) {
console.log(i + ": " + table[i]);
}
}
}
}
return HashTable;
})()