數據結構之「哈希表」

什麼是哈希表?

哈希表(Hash table, 也叫散列表),是根據鍵(Key)來直接訪問在內存存儲位置的數據結構。它經過一個哈希函數將所須要查詢的數據映射到一張哈希表中,來提高查詢效率。
哈希函數的實現方法:
1.除留餘數法
取關鍵字被某個不大於哈希表表長的數除後所得的餘數爲散列地址。
2.摺疊法
將關鍵字分割成位數相同的幾部分(最後一部分的位數能夠不一樣),而後取這幾部分的疊加和(捨去進位)做爲哈希地址。
3.平方取中法
取關鍵字平方後的中間幾位爲哈希地址。
4.直接定址法
取關鍵字或關鍵字的某個線性函數值爲哈希地址。java

哈希衝突

無論用什麼哈希函數去計算哈希地址,都是會產生哈希衝突的,所以咱們須要想辦法解決哈希衝突,而且在設計哈希函數時,儘量減小哈希衝突。
1.單獨的鏈表法
在哈希表的後面單獨鏈上一個單鏈表來存儲衝突的元素,JDK 1.8 裏的 HashMap 就是選擇的這種方式解決衝突的,不過它對鏈表作了一層優化。當元素個數大於等於 8 時,會把鏈表轉換成紅黑樹,提高查詢效率。
2.線性探測法
當發生哈希衝突時,逐個探測存放地址的表,直到查找到一個空單元。這個方式不便於查找,不建議使用。
3.創建一個公共溢出區
當發生哈希衝突時,就把元素存入到公用的溢出區,查詢時遍歷溢出區。
從上面這幾種處理方法來講,仍是鏈表法效率比較高,推薦使用。不過都有現成的工具類使用,所以只須要知道實現原理,最好本身能夠去寫代碼實現它。
哈希表算法

哈希表有什麼用?

哈希表在平常開發中仍是比較經常使用的,由於它最優的查詢時間複雜度是 O(1),當哈希衝突比較嚴重的時候,查詢效率就至關於線性的,所以哈希算法直接影響到查詢的效率。數組

哈希表怎麼實現的?

哈希表的結構微信

public class HashMap<K,V> {
    //用節點數組看成哈希表
    Node<K,V>[] table;
    int size;
    //節點
    static class Node<K,V> {
        //哈希值
        final int hash;
        //鍵
        final K key;
        //值
        V value;
        //哈希值衝突時存儲
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }
}

總結

哈希表是一個鍵值對的存儲結構,而且根據鍵進行哈希算法找到對應的存儲位置。哈希算法會直接影響到哈希表的查詢效率,通常選擇哈希衝突小的實現方式,以便提高查詢效率。當哈希衝突時,通常選擇鏈表來存儲衝突的元素,當衝突的元素增多時,能夠採用紅黑樹來存儲,以提高查詢效率。JDK 1.8 版本的 HashMap,當鏈表個數大於等於 8 時,就是採用紅黑樹來存儲的。在知道元素個數時,初始化哈希表時直接指定哈希表大小,由於當元素達到哈希表大小時,會作 resize 操做。當元素愈來愈多時,resize 是很耗時的,至關於重建哈希表。所以直接指定哈希表大小,減小 resize 次數以便提高插入性能。數據結構

PS:
清山綠水始於塵,博學多識貴於勤。
我有酒,你有故事嗎?
微信公衆號:「清塵閒聊」。
歡迎一塊兒談天說地,聊代碼。函數

相關文章
相關標籤/搜索