1. 程式人生 > >哈希表的理解

哈希表的理解

art 5.1 href 說明 自身 成了 現在 理解 不同

哈希表是種數據結構,它可以提供快速的插入操作和查找操作。第一次接觸哈希表時,它的優點多得讓人難以置信。不論哈希表中有多少數據,插入和刪除(有時包括側除)只需要接近常量的時間即0(1)的時間級。實際上,這只需要幾條機器指令。

  對哈希表的使用者一一人來說,這是一瞬間的事。哈希表運算得非常快,在計算機程序中,如果需要在一秒種內查找上千條記錄通常使用哈希表(例如拼寫檢查器)哈希表的速度明顯比樹快,樹的操作通常需要O(N)的時間級。哈希表不僅速度快,編程實現也相對容易。

哈希表也有一些缺點它是基於數組的,數組創建後難於擴展某些哈希表被基本填滿時,性能下降得非常嚴重,所以程序雖必須要清楚表中將要存儲多少數據(或者準備好定期地把數據轉移到更大的哈希表中,這是個費時的過程)。

如果不需要有序遍歷數據,井且可以提前預測數據量的大小。那麽哈希表在速度和易用性方面是無與倫比的。

哈希表算法-哈希表的概念及作用

哈希表簡單的理解:在記錄的存儲位置和它的關鍵字之間建立一個確定的對應關系f,使每個關鍵字和結構中一個唯一的存儲位置相對應。

舉例:

哈希表最常見的例子是以學生學號為關鍵字的成績表,1號學生的記錄位置在第一條,10號學生的記錄位置在第10條...

如果我們以學生姓名為關鍵字,如何建立查找表,使得根據姓名可以直接找到相應記錄呢?

技術分享

上面這張表即哈希表。

如果將來要查李秋梅的成績,可以用上述方法求出該記錄所在位置:

李秋梅:lqm 12+17+13=42 取表中第42條記錄即可。

問題:如果兩個同學分別叫 劉麗 劉蘭 該如何處理這兩條記錄?

這個問題是哈希表不可避免的,即沖突現象:對不同的關鍵字可能得到同一哈希地址。

哈希表算法-處理沖突的方法

如果兩個同學分別叫 劉麗 劉蘭,當加入劉蘭時,地址24發生了沖突,我們可以以某種規律使用其它的存儲位置,如果選擇的一個其它位置仍有沖突,則再選下一個,直到找到沒有沖突的位置。選擇其它位置的方法有:

1、開放定址法

Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)

其中m為表長,di為增量序列

如果di值可能為1,2,3,...m-1,稱線性探測再散列。

如果di取值可能為1,-1,2,-2,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2)

稱二次探測再散列。

如果di取值可能為偽隨機數列。稱偽隨機探測再散列。

比如有一組關鍵字{12,13,25,23,38,34,6,84,91},Hash表長為11,Hash函數為address(key)=key%11,當插入12(hash(12)=1),13(hash(13)=2),25(hash(25)=3)時可以直接插入,而當插入23時,地址1被占用了,因此沿著地址1依次往下探測(探測步長可以根據情況而定,如(hash(23)+1)%11=2,(hash(23)+2)%11=3,(hash(23)+3)%11=4),直到探測到地址4,發現為空,則將23插入其中。

2、再哈希法

當發生沖突時,使用第二個、第三個、哈希函數計算地址,直到無沖突時。缺點:計算時間增加。

3、鏈地址法

將所有關鍵字為同義詞的記錄存儲在同一線性鏈表中。

技術分享

雖然能夠采用一些辦法去減少沖突,但是沖突是無法完全避免的。因此需要根據實際情況選取解決沖突的辦法。

哈希表算法-哈希表的構造方法

1、直接定址法

例如:有一個從1到100歲的人口數字統計表,其中,年齡作為關鍵字,哈希函數取關鍵字自身。

但這種方法效率不高,時間復雜度是O(1),空間復雜度是O(n),n是關鍵字的個數

技術分享

2、數字分析法

有學生的生日數據如下:

年.月.日

75.10.03
75.11.23
76.03.02
76.07.12
75.04.21
76.02.15
...

經分析,第一位,第二位,第三位重復的可能性大,取這三位造成沖突的機會增加,所以盡量不取前三位,取後三位比較好。

3.平方取中法

  對關鍵字進行平方運算,然後取結果的中間幾位作為Hash地址。假如有以下關鍵字序列{421,423,436},平方之後的結果為{177241,178929,190096},那麽可以取{72,89,00}作為Hash地址。

4、折疊法

將關鍵字分割成位數相同的幾部分(最後一部分的位數可以不同),然後取這幾部分的疊加和(舍去進位)作為哈希地址,這方法稱為折疊法。

例如:每一種西文圖書都有一個國際標準圖書編號,它是一個10位的十進制數字,若要以它作關鍵字建立一個哈希表,當館藏書種類不到10,000時,可采用此法構造一個四位數的哈希函數。如果一本書的編號為0-442-20586-4,則:

技術分享

5.除留取余法

  如果知道Hash表的最大長度為m,可以取不大於m的最大質數p,然後對關鍵字進行取余運算,address(key)=key%p。

  在這裏p的選取非常關鍵,p選擇的好的話,能夠最大程度地減少沖突,p一般取不大於m的最大質數。

6、隨機數法

選擇一個隨機函數,取關鍵字的隨機函數值為它的哈希地址,即

H(key)=random(key) ,其中random為隨機函數。通常用於關鍵字長度不等時采用此法。

Hash表大小的確定

  Hash表大小的確定也非常關鍵,如果Hash表的空間遠遠大於最後實際存儲的記錄個數,則造成了很大的空間浪費,如果選取小了的話,則容易造成沖突。在實際情況中,一般需要根據最終記錄存儲個數和關鍵字的分布特點來確定Hash表的大小。還有一種情況時可能事先不知道最終需要存儲的記錄個數,則需要動態維護Hash表的容量,此時可能需要重新計算Hash地址。

Hash表的平均查找出長度

Question1:

將關鍵字序列(7、8、30、11、18、9、14)散列存儲到散列表中。散列表的存儲空間是一個下標從0開始的一維數組,散列函數為: H(key) = (keyx3) MOD 7,處理沖突采用線性探測再散列法,要求裝填(載)因子為0.7。

(1) 請畫出所構造的散列表。

(2) 分別計算等概率情況下查找成功和查找不成功的平均查找長度。

Ans:

(1).首先明確一個概念裝載因子,裝載因子是指所有關鍵子填充哈希表後飽和的程度,它等於 關鍵字總數/哈希表的長度。 根據題意,我們可以確定哈希表的長度為 L = 7/0.7 = 10;因此此題需要構建的哈希表是下標為0~9的一維數組。根據散列函數可以得到如下散列函數值表。

H(Key) = (keyx3) MOD 7, 例如key=7時, H(7) = (7x3)%7 = 21%7=0,其他關鍵字同理。

技術分享

采用線性探測再散列法處理沖突,所構造的散列表為:

技術分享

下面對散列表的構造方式加以說明,註意表1中的關鍵字7和14,30和9, 11和18,這三組關鍵子的H(Key)值相同,這在構建散列表時就會產生沖突,因為他們的地址相同,所以要通過一定的沖突處理方法來解決這個問題。依題,采用線性探測再散列法處理沖突。下面詳細介紹如何構建散列表:

第一個key 7,它的地址是0,因此放到散列表的數組下表為0的位置,這個位置上沒有關鍵字,因此沒有沖突可以直接填入;

第二個key 8,它的地址是3,因此放到散列表的數組下表為3的位置,這個位置上沒有關鍵字,因此沒有沖突可以直接填入;

第三個key 30,它的地址是6,因此放到散列表的數組下表為6的位置,這個位置上沒有關鍵字,因此沒有沖突可以直接填入;

第四個key 11,它的地址是5,因此放到散列表的數組下表為5的位置,這個位置上沒有關鍵字,因此沒有沖突可以直接填入;

第五個key 18,它的地址是5,因此放到散列表的數組下表為5的位置,但這個位置上已經有關鍵字11,遇到了沖突,此時我們根據線性探測再散列法來處理這個沖突,探測下一個位置6, 6這個位置上已經存在關鍵字30則繼續增加步長1,因此現在的新地址應為7,位置7上沒有關鍵字,放入即可,到此沖突已經解決;

第六個key 9,它的地址是6,因此放到散列表的數組下表為6的位置,但這個位置上已經有關鍵字30,遇到了沖突,探測下一個位置7, 7這個位置上已經存在關鍵字18則繼續增加步長1,因此現在的新地址應為8,位置8上沒有關鍵字,放入即可;

第七個key 14,它的地址是0,因此放到散列表的數組下表為0的位置,但這個位置上已經有關鍵字7,遇到了沖突,探測下一個位置1, 位置1上沒有關鍵字,放入即可;

到這一步所有關鍵字均已填入,散列表已經構造完成,如表2所示。

(2)等概率情況下查找成功平均查找長度:

這一問可以根據第一問的構造過程求解:

key7一次就填入了表中,因此查找次數為1,同理8, 30, 11查找次數均為1; key18 進行了3次放入操作,探測位置分別是5,6,7 ,因此查找次數為3;key9也是3次;key14 進行了兩次探測,因此查找次數為2。次數表如表3所示

技術分享

所以ASLsuccess= (1+1+1+1+3+3+2)/ 7 = 12/7。

等概率情況下查找不成功的平均查找長度:

接下來討論不成功的情況, 看表2,計算查找不成功的次數就直接找關鍵字到第一個地址上關鍵字為空的距離即可, 但根據哈希函數地址為MOD7,因此初始只可能在0~6的位置。等概率情況下,查找0~6位置查找失敗的查找次數為:

看地址0,到第一個關鍵字為空的地址2的距離為3,因此查找不成功的次數為3.

地址1, 到第一個關鍵為空的地址2的距離為2,因此查找不成功的次數為2.

地址2, 到第一個關鍵為空的地址2的距離為1,因此查找不成功的次數為1.

地址3,到第一個關鍵為空的地址4的距離為2,因此查找不成功的次數為2.

地址4,到第一個關鍵為空的地址4的距離為1,因此查找不成功的次數為1.

地址5,到第一個關鍵為空的地址2(註意不是地址9,因為初始只可能在0~6之間,因此循環回去)的距離為5,因此查找不成功的次數為5.

地址6,到第一個關鍵為空的地址2(註意不是地址9,因為初始只可能在0~6之間,因此循環回去)的距離為4,因此查找不成功的次數為4.

因此查找不成功的次數表如下表所示

技術分享

哈希表的理解