數據結構和算法----散列表

散列表

  • 定義

散列表是根據(key value)來直接進行訪問的數據結構。它通過把關鍵碼應射鵰一個數組中的一個位置來訪問記錄,以加快查找的速度。這個映射的函數叫散列函數。存放記錄的數組叫做散列表

  • 散列能做什麼

例如word的單詞拼寫檢查功能,假設有一百萬個單詞,每個單詞平局長度爲10個字母,也就是佔用十字節的空間。100萬個單詞四捨五入也就是佔用10M的空間。我們將其映射到散列表中。當用戶輸入時就去散列表中查找。如果查不到,則說明拼寫錯誤予以提示。

  • 散列函數

散列函數,顧名思義他是一個函數。我們可以把它定義成hash(key),其中key表示元素的鍵值,hash(key)的值表示經過散列函數計算得到的散列值。

  • 構造散列函數的要求
  1. 散列函數計算得到的散列值是一個非負整數
  2. 如果key1 = key2,那hash(key1) == hash(key2)
  3. 如果key1 != key2, hash(key1) != hash(key2)
  4. 儘量的簡單,速度快
  5. 散列表長度儘量爲素數。這樣可以使映射分配均勻

假設有兩個散列表,a表長度爲7b表長度爲8,步長爲2的產生數據。假設數據只到1000

那麼a表分佈爲

b表分佈爲

可以非常明顯地看到,a表均勻的分佈。但是b表堆積明顯

  • 散列衝突

如果key1 != key2, hash(key1) == hash(key2),我們稱之爲散列衝突。想要避免散列衝突幾乎不可能。即使MD5SHACRC等哈希算法,也無法完全避免散列衝突。

  • 散列衝突的解決
  1. 分離鏈接法

簡單來說就是再原有的散列表後加上鍊表來存放散列衝突的元素。

優點:

可以解決任意次衝突

刪除操作簡單、統一

缺點:

耗費內存

空間並不連續,緩存幾乎失效

  1. 線性探測法

當散列表插入數據遇到衝突時,將其放入下一個空閒地址。

線性探測的效率視裝填因子大小而定

(裝填因子 = 填入表中元素個數 / 散列表的長度)

  1. 平方探測法

當散列衝突時查找1^2遠(+-1)處是否爲空,如果還衝突則找2^2遠處以此類推。

定理:如果使用平方探測,且表的大小爲素數,那麼當表至少有一半是空的時候,總能夠插入一個新的元素

  1. 雙散列

雙散列可以看做Fi= i * hash2( x ) 其基本策略和線性探測法一項,唯一不同是:它不是檢查衝突位置後的每一個位置,而是採用另一個散列函數產生一個固定的增量。

注:第二個散列函數要仔細選擇,需滿足條件

1)排除散列值是0的情況

2)產生的散列值必須與表長M互素

七、散列優化

     1、再散列

        當裝載因子過大時,操作時間將開始過長,插入操作可能失敗。解決辦法是,新建個大約長度爲散列表兩倍的新表,掃描整個原始散列,計算所有元素新的散列值插入新的散列表中。

  1. 鏈接法缺陷解決

如果分離鏈接法鏈表過長,會嚴重影響性能,鏈表就要轉爲紅黑樹(一般再長度爲8時轉成紅黑樹),利用紅黑樹快速增刪改查的特點,

提高性能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章