哈希算法-快速查表的原理


 

  在實際問題中,按照給定的值進行數據查詢是經常遇到的,比如,在電話號碼簿中查詢某個人的電話號碼;在圖書館中按照ISBN 編號查找某本書的位置;在地圖中按照坐標查找某個地點的地名等等。

字典的定義

  我們都使用過字典,如英漢字典、成語字典,圖書的檢索目錄、電話簿等也可以看作廣義上的字典。在計算機科學中,把字典也當成一種數據結構。

  我們把字典定義為“鍵-值對”(Key-Value Pair) 的集合。根據不同的問題,我們為名字和值賦予不同的含義,比如,在英漢字典中,英文單詞是名字,此單詞的中文解釋條目是值;在電話簿中,人名是名字,此人名對應的電話號碼是值。

  字典最基本的操作包括:find(查找)、add(插入)、remove(刪除),分別用來從字典中檢索數據、插入數據和刪除數據。在實際存儲中,我們將“鍵-值對”存儲於記錄中,通過鍵來標識該“鍵-值對”。“鍵-值對”的存放位置和其鍵之間的對應關系用一個二元組表示: (鍵, 值的位置) 。

  從字典中查找“鍵-值對”的最簡單方法就是使用數組存儲,然后在查找的時候遍歷此數組,當遍歷到和被查找的“鍵-值對”的名字相同項的時候,這個“鍵-值對”就被找到了。

  這種最朴實的方式肯定是不能滿足實際要求的,因此人們發明了一種檢索效率非常高的組織字典數據的方法 ,即哈希表結構。

 

哈希表與哈希方法

  哈希方法:在鍵與“鍵-值對”的存儲位置之間建立一個確定的對應函數關系 hash() ,使得每一個鍵與結構中的一個唯一的存儲位置相對應:

  存儲位置=hash(鍵)

  在搜索時,首先對鍵進行hash 運算,把求得的值當做“鍵-值對”的存儲位置,在結構中按照此位置取“鍵- 值對”進行比較,若鍵相等,則表示搜索成功。

  在存儲“鍵-值對”的時候,依照相同的hash函數計算存儲位置,並按此位置存放,這種方法就叫做哈希方法,也叫做散列方法。在哈希方法中使用的轉換函數 hash 被稱作哈希函數(或者散列函數)。

  按照此中算法構造出來的表叫做哈希表(或者散列表) 。

  哈希函數建立了從“鍵-值對”到哈希表地址集合的一個映射,有了哈希函數,我們就可以根據鍵來確定“鍵-值對”在哈希表中的位置的地址。使用這種方法由於不必進行多次鍵的比較,所以其搜索速度非常快,很多系統都使用這種方法進行數據的組織和檢索。

 

沖突與沖突的解決

  通常鍵的取值范圍比哈希表地址集合大很多,因此有可能經過同一哈希函數的計算,把不同的鍵映射到了同一個地址上面,這就叫沖突。比如,有一組“鍵-值對”,其鍵分別為12361、7251、3309、30976,采用的哈希函數是:

  public static int hash(int key) {

    return key%73+13420;

  }

  則將會得到hash(12361)=hash(7251)=hash(3309)=hash(30976)=13444 ,即不同的鍵通過哈希函數對應到了同一個地址,我們稱這種哈希計算結果相同的不同鍵為同義詞。

  如果“鍵-值對”在加入哈希表的時候產生了沖突,就必須找另外一個地方來存放它,沖突太多會降低數據插入和搜索的效率,因此希望能找到一個不容易產生沖突的函數,即構 造一個地址分布比較均勻的哈希函數。

  常用的哈希函數包括:直接定址法、數字分析法、除留余數法、乘留余數法、平方取中法、折疊法等。應該根據實際工作中關鍵碼的特點選用適當的方法。

 

  雖然采用合適的哈希方法能夠降低沖突的概率,但是沖突仍然是不可避免的,處理沖突的最常用方法就是“桶”算法:假設哈希表有m 個地址,就將其改為 m 個“桶”,其桶號與哈希地址一一對應,每個桶都用來存放互為同義詞的鍵,也就是如果兩個不同的鍵用哈希函數計算得到了同一個哈希地址,就將它們放到同一個桶中,檢索的時候在桶內進行順序檢索。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM