數據結構與算法分析(十二)散列表

  1. 散列表的英文叫“Hash Table”,我們平時也叫它“哈希表”或者“Hash 表
  2. 散列表用的是數組支持按照下標隨機訪問數據的特性,所以散列表其實就是數組的一種擴展,由數組演化而來。可以說,如果沒有數組,就沒有散列表。
  3. 散列表的由來?
    1. 散列表來源於數組,它藉助散列函數對數組這種數據結構進行擴展,利用的是數組支持按照下標隨機訪問元素的特性。
    2. 需要存儲在散列表中的數據我們稱爲鍵,將鍵轉化爲數組下標的方法稱爲散列函數,散列函數的計算結果稱爲散列值。
    3. 將數據存儲在散列值對應的數組下標位置。
  4. 如何設計散列函數?
    1. 散列函數計算得到的散列值是一個非負整數。
    2. 若key1=key2,則hash(key1)=hash(key2)
    3. 若key≠key2,則hash(key1)≠hash(key2)
    4. 正是由於第3點要求,所以產生了幾乎無法避免的散列衝突問題。
  5. 散列衝突的解放方法?
    1. 常用的散列衝突解決方法有2類:開放尋址法(open addressing)和鏈表法(chaining)
    2. 開放尋址法
      1. ①核心思想:如果出現散列衝突,就重新探測一個空閒位置,將其插入。
        ②線性探測法(Linear Probing):
        插入數據:當我們往散列表中插入數據時,如果某個數據經過散列函數之後,存儲的位置已經被佔用了,我們就從當前位置開始,依次往後查找,看是否有空閒位置,直到找到爲止。
        查找數據:我們通過散列函數求出要查找元素的鍵值對應的散列值,然後比較數組中下標爲散列值的元素和要查找的元素是否相等,若相等,則說明就是我們要查找的元素;否則,就順序往後依次查找。如果遍歷到數組的空閒位置還未找到,就說明要查找的元素並沒有在散列表中。
        刪除數據:爲了不讓查找算法失效,可以將刪除的元素特殊標記爲deleted,當線性探測查找的時候,遇到標記爲deleted的空間,並不是停下來,而是繼續往下探測。
        結論:最壞時間複雜度爲O(n)
        ③二次探測(Quadratic probing):線性探測每次探測的步長爲1,即在數組中一個一個探測,而二次探測的步長變爲原來的平方。
        ④雙重散列(Double hashing):使用一組散列函數,直到找到空閒位置爲止。
        ⑤線性探測法的性能描述:
        用“裝載因子”來表示空位多少,公式:散列表裝載因子=填入表中的個數/散列表的長度。
        裝載因子越大,說明空閒位置越少,衝突越多,散列表的性能會下降。
    3. 鏈表法(更常用)插入數據:當插入的時候,我們需要通過散列函數計算出對應的散列槽位,將其插入到對應的鏈表中即可,所以插入的時間複雜度爲O(1)。
      查找或刪除數據:當查找、刪除一個元素時,通過散列函數計算對應的槽,然後遍歷鏈表查找或刪除。對於散列比較均勻的散列函數,鏈表的節點個數k=n/m,其中n表示散列表中數據的個數,m表示散列表中槽的個數,所以是時間複雜度爲O(k)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章