JS散列表

散列表 HashTable

通過鍵值對儲存的一種數據結構(key,value),通過鍵值(key)查找(value)。只查找一次,不需要n次遍歷。查找時間爲一個常量,即數據量的大小不會影響查找速度。
平均查找時間爲O(1),對比二分法的查找時間爲O(logn),線性查找爲O(n)要快很多。
最壞情況查找時間情況下查找時間爲線性時間O(n)。
數據增減和查找性能一致。也爲O(1),O(n)。

性能受到以下因素影響:

  • 裝填因子:已裝填的數據/總容量,也就是空餘位置越多,發生衝突可能性越小,性能越好。
  • 良好的散列函數 : 讓數組中的值成均勻分佈。儘量不要扎堆。

JS中的散列表

直接創建

最快的實現方式是直接創建對應格式

var a = new Array(); // or just []
a[0] = 0;
a['one'] = 1;
a['two'] = 2;
a['three'] = 3;

for (var k in a) {
    if (a.hasOwnProperty(k)) {
        console.log('key is: ' + k + ', value is: ' + a[k]);
          <!--  key is: 0, value is: 0
                key is: one, value is: 1 ... -->
    }
}
console.log(a.length); //1

但是這樣有一問題,通過a.length可發現只有對數字的key有效,對string的key無效。
就是說a.length只計算了a[0]。因爲js會在創建對象時,把key分爲數字number a[0]或成員 memeber a['one']
而在計算長度時也就是indexed key,會忽略string的key。

自建HashTable

創建數組保存 var tabe = []
利用transHashCode把key轉換成數字=每個字母的ASCII碼值相加的除以37的餘數
假設目標key是Jack,那麼transHashCode(Jack)=5,增刪查(put,get,remove)的目標就是table[5]

默認基本散列,但是沒有考慮hash值重複。

function HashTable() {
    var table = [];
    var transHashCode = function (key) {
        var hash = 0;
        for (var i = 0; i < key.length; i++) {
            hash += key.charCodeAt(i); 
        }
        return hash % 37;
    };

    this.put = function(key, value) {
        var position = loseloseHashCode(key); 
        table[position] = value; 
    };

    this.get = function (key) {
        return table[loseloseHashCode(key)]; 
    };

    this.remove = function(key) {
        table[loseloseHashCode(key)] = undefined;
    };
}

當兩個key的HASH值相等時,需要解決衝突。目前常用有 連接

  • 分離連接:在散列表每一個位置創建鏈表,也就是多個HASH值相等的key在同一個散列表位置下的不同鏈表。這樣的問題是長度很難保持均衡。
  • 分離連接:出現重複後,通過位置+1的方式,排到後面位置。
  • 增加transHashCode的複雜度,來減少出現相同的情況。
    比如:
var djb2HashCode = function (key) {
    var hash = 5381; // 一個較大的素數基準值
    for (var i = 0; i < key.length; i++) {
        hash = hash * 33 + key.charCodeAt(i); // 基準值乘以33再加ASCII碼值
    }
    return hash % 1013; //除以1013取餘
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章