散列的概念、構造散列函數以及解決沖突的方法


定義


 

  散列表(Hash Table,也稱哈希表),是一種根據鍵(Key而直接訪問在內存存儲位置的數據結構。也就是說,它通過計算一個關於鍵值的函數,將所需查詢的數據映射到表中一個位置來訪問記錄,這加快了查找速度。這個映射函數稱為散列函數,存放記錄的數組稱做散列表

 

概念


 

1、若其關鍵字為k,則其值存放在 f(k) 的存儲位置上。因此不需要比較即可直接取得所查記錄。稱這個對應關系 f 為散列函數,按照這個思想建立的表叫散列表

2、對不同的關鍵字可能得到同一個散列地址,即k1 != k2,而 f(k1) = f(k2),這種情況稱之為沖突(Collision)。具有相同函數值的關鍵字對該散列函數來說稱為同義詞(Synonym)

3、綜上所述,根據散列函數 f(k) 和處理沖突的方法將一組關鍵字映射到一個有限的連續的地址集(區間)上,並以關鍵字在地址集中的“像”作為記錄在表中的存儲位置,這種表便稱為散列表,這一映射過程稱為散列造表或者是散列,所得的存儲位置稱散列地址

4、若對於關鍵字集合中的任一個關鍵字,經散列函數映象到地址集合中任何一個地址的概率是相等的,則稱此類散列函數為均勻散列函數(Uniform Hash function),這就是使關鍵字經過散列函數得到一個“隨機的地址”,從而減少沖突。

 

Hash函數的構造方法


 

  散列函數能使對一個數據序列的訪問過程更加迅速有效,通過散列函數,數據元素將被更快定位。

影響哈希查找效率的一個重要因素是哈希函數本身。當兩個不同的數據元素的哈希值相同時,就會發生沖突。為減少發生沖突的可能性,哈希函數應該將數據盡可能分散地映射到哈希表的每一個表項中。

下面是幾種定址方法:

1、直接定址法:取關鍵字或關鍵字的某個線性函數值為散列地址。即 Hash(k) = k 或 hash(k) = ak+b,其中 a b為常數(這種散列函數叫做自身函數)

2、數字分析法:假設關鍵字是以r為基的數,並且哈希表中可能出現的關鍵字都是事先知道的,則可取關鍵字的若干數位組成哈希地址。比如有一組value1=112233,value2=112633,value3=119033,針對這樣的數我們分析數中間兩個數比較波動,其他數不變。那么我們取key的值就可以是key1=22,key2=26,key3=90。

3、平方中取法:取關鍵字平方后的中間幾位為哈希地址。通常在選定哈希函數時不一定能知道關鍵字的全部情況,取其中的哪幾位也不一定合適,而一個數平方后的中間幾位數和數的每一位都相關,由此使隨機分布的關鍵字得到的哈希地址也是隨機的。取的位數由表長決定。

4、折疊法:將關鍵字分割成位數相同的幾部分(最后一部分的位數可以不同),然后取這幾部分的疊加和(舍去進位)作為哈希地址。舉個例子,比如value=135790,要求key是2位數的散列值。那么我們將value變為13+57+90=160,然后去掉高位“1”,此時key=60,這就是他們的哈希關系,這樣做的目的就是key與每一位value都相關,來做到“散列地址”盡可能分散的目地。

5、隨機數法

6、除留余數法:取關鍵字被某個不大於散列表表長m的數p除后所得的余數為散列地址,即hash(k) = k mod p, p <= m。不僅可以對關鍵字直接取模,也可在折疊法、平方取中法等運算之后取模。對p的選擇很重要,一般取素數或m,若p選擇不好,容易產生沖突。

 

處理沖突的辦法


 

  為了知道沖突產生的相同散列函數地址所對應的關鍵字,必須選用另外的散列函數,或者對沖突結果進行處理。而不發生沖突的可能性是非常之小的,所以通常對沖突進行處理。常用的辦法如下:

 

1、鏈接地址法:

將哈希值相同的數據元素存放在一個鏈表中,在查找哈希表的過程中,當查找到這個鏈表時,必須采用線性查找方法。

舉個例子:關鍵字為{ 41,26,68,15,44,6,36,38,12,51}的一組數據插入散列表,並假定以關鍵字除以13的余數為散列函數的法則。

 

2、開放定址法:

  公式:

  其中 hash(key) 為散列函數,m 為散列表長,di 為增量序列,i為已發生的沖突次數。

  增量序列有下面三種取法:

    I)di = 1,2,3...m-1 稱為線性探測(Linear Probing)即 di = i,或者為其他線性函數。相當於逐個探測存放地址的表,如果為空,把數據放在空的位置。

    II)di = (+ 1^2) or (- 1^2),(+ 2^2) or (- 2^2) ... + (k^2) or (- k^2) 稱為平方探測(Quadratic Probing)  相對於線性探測,相當於發生沖突時探測間隔 di = i^2 個單元的位置是否為空,如果為空則把數據放到空的位置。

    III)di = 偽隨機數序例,稱為偽隨機探測

  給出一個用線性探測填裝一個散列表的過程:

  關鍵字為{89,18,49,58,69}插入到一個散列表中的情況,此時線性探測的方法是取 di = i,並假定取關鍵字除以10的余數為散列函數法則。

  第一次沖突發生在填裝49的時候。地址為9的單元已經填裝了89這個關鍵字,所以取 i = 1,往下查找一個單位,發現為空,所以將49填裝在地址為0的空單元。第二次沖突則發生在58上,取 i = 2,往下查找兩個單位,將58填裝在地址為1的空單元。69同理。

表的大小選取至關重要,此處選取10作為大小,發生沖突的幾率就比選擇質數11作為大小的可能性大。越是質數,mod取余就越可能均勻分布在表的各處。

 

3、再散列:

  公式:

  Hashi 是某些散列函數。即上次散列發生沖突時,利用該沖突地址進行再散列,直到沖突不再發生。該辦法不易發生分布不均勻的情況,但增加了計算時間。

  舉個例子,現有一序列 <37, 83, 97, 78, 14, 59, 25, 72>,畫出構建哈希表的過程,哈希函數是 hash(i) = i mod 11,解決沖突的辦法是再散列( mod 9)。

  前五個插入都沒有問題。當插入 59 時,h(59,0) = (59 mod 11 ) mod 11 = 4,位置 4 與 37 沖突,繼續計算。沖突 1 次,i = 1,h(59,1) = (59 mod 11 + 1*(1+59 mod 9)) mod 11 = 10,位置 10 空,59 插入到位置 10 。如果再沖突,那么 i = 2,繼續計算,以此類推。25 和 72 類似。

 

ASL成功/不成功 的求法


  

  關於哈希表求查找成功與查找成功時的平均查找長度的題目,我覺得這篇博客說的不錯。  

 


免責聲明!

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



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