數據結構----散列

/*
* 算法——散列
* 散列表是基於數組進行設計的。數組的長度是預先設定的
* 全部元素根據和該元素對應的鍵,保存在數組的特定位置,該鍵和咱們前面講到的字典中的鍵是相似的概念
* 使用散列表存儲數據時,經過一個散列函數將鍵映射爲一個數字,這個數字的範圍是 0 到散列表的長度。
*
* 這裏所說的鍵 應該就是數組的索引 只不過 數組既然長度肯定了,那麼索引的個數也是肯定了
* 每一個元素是無限的,每一個元素的鍵值映射出來的索引也許就會發生重複或說碰撞。 這個叫有效碰撞。
*
* 鍵值映射到數組的索引 這個過程是由散列函數來完成。 散列函數的選擇 要保證鍵值映射出來的索引是儘可能不重複的
*
* simpleHash: 散列函數
*
* put: 在散列中增長元素
*
* showDistro: 展現散列中的元素
* */
function simpleHash(data) {
    var total = 0;
    for(var i = 0 ; i < data.length; i++) {
        total += data.charCodeAt(i);
    }
    return total % this.table.length;
}
function put(data) {
    var pos = this.simpleHash(data);
    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])
        }
    }
}
function HashTable() {
    this.table = new Array(137);
    this.buildChains = buildChains;
    this.simpleHash = simpleHash;
    this.put = put;
    this.showDistro = showDistro;
}
var someNames = ["David", "Jennifer", "Donnie", "Raymond",
    "Cynthia", "Mike", "Clayton", "Danny", "Jonathan"],
    h = new HashTable();
// h.buildChains();  //測試線性探測法 註釋掉
for (var i = 0; i< someNames.length;i++) {
    h.put(someNames[i]);
}
h.showDistro(); // 輸出:35: Cynthia 45: Clayton 57: Donnie 77: David 95: Danny 116: Mike 132: Jennifer 134: Jonathan

//是輸出了8位少了一位? 記得上面的說明 散列函數可能會映射相同的索引出來 出現了有效碰撞。

//更好的散列函數 數組長度是質數 計算過程當中再乘以一個質數

//爲何要選擇一個質數呢? 質數特色:只有1 和 自己兩個因數 而合數 有兩個以上因數 若是除餘合數 那麼形成重複機會大
//由於合數有多個因子 好比 20   50%20 70%20 是同樣的

//感受這個質數不是特別靠譜 ^^ 下面有其它方法解決

function simpleHash(data) {
    const H = 5;
    var total = 0;
    for (var i = 0; i < data.length; ++i) {
        total += H * total + data.charCodeAt(i);
    }
    return total % this.table.length;
}

/*碰撞處理
* 一、開鏈法:開鏈法是指實現散列表的底層數組中,每一個數組元素又是一個新的數據結構,好比另外一個數組,這樣就能存儲多個鍵了
* 二、線性探測法 線性探測法檢查散列表中的下一個位置是否爲空。若是爲空,就將數據存入該位置;若是不爲空,則繼續檢查下一個位置,直到找到一個空的位置爲止
* */
/*
* 兩個方法該如何選擇?
* 當存儲數據使用的數組特別大時,選擇線性探測法要比開鏈法好。這裏有一個公式,經常
 能夠幫助咱們選擇使用哪一種碰撞解決辦法:若是數組的大小是待存儲數據個數的 1.5 倍,
 那麼使用開鏈法;若是數組的大小是待存儲數據的兩倍及兩倍以上時,那麼使用線性探
 測法。
* */
/*下面這些方法是對上面的方法從新或新增*/

/*開鏈法*/

function buildChains() {
    for(var i = 0; i < this.table.length;i++) {
        this.table[i] = new Array();
    }
}
// function showDistro() {
//     for(var i = 0 ; i < this.table.length;i++) {
//         if (this.table[i][0] !== undefined) {
//             console.log(i + ":" +this.table[i])
//         }
//     }
// }
// function put(data) {
//     var pos = this.simpleHash(data);
//     this.table[pos].push(data);
// }

/*線性探測法*/

function put(data) {
    var pos = this.simpleHash(data);
    while (this.table[pos] !== undefined) {
        pos++;
    }
    this.table[pos] = data;
}
相關文章
相關標籤/搜索