javascript 散列表(Hashes)算法與說明

散列表的介紹

散列算法的作用是儘可能快地在數據結果中找到一個值,通常在數據結果中獲得一個值(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;
})()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章