一.概念
雜湊表就是一種以 鍵-值(key-indexed) 儲存資料的結構,我們只要輸入待尋找的值即key,即可尋找到其對應的值。
雜湊的思路很簡單,如果所有的鍵都是整數,那麼就可以使用一個簡單的無序數組來實現:將鍵作為索引,值即為其對應的值,這樣就可以快速存取任意鍵的值。這是對於簡單的鍵的情況,我們將其擴充到可以處理更加複雜的類型的鍵。
使用雜湊尋找有兩個步驟:
1. 使用雜湊函數將被尋找的鍵轉換為數組的索引。在理想的情況下,不同的鍵會被轉換為不同的索引值,但是在有些情況下我們需要處理多個鍵被雜湊到同一個索引值的情況。所以雜湊尋找的第二個步驟就是處理衝突
2. 處理雜湊碰撞衝突。有很多處理雜湊碰撞衝突的方法,本文後面會介紹拉鏈法和線性探測法。
雜湊表是一個在時間和空間上做出權衡的經典例子。如果沒有記憶體限制,那麼可以直接將鍵作為數組的索引。那麼所有的尋找時間複雜度為O(1);如果沒有時間限制,那麼我們可以使用無序數組並進行順序尋找,這樣只需要很少的記憶體。雜湊表使用了適度的時間和空間來在這兩個極端之間找到了平衡。只需要調整雜湊函數演算法即可在時間和空間上做出取捨。
在Hash表中,記錄在表中的位置和其關鍵字之間存在著一種確定的關係。這樣我們就能預Crowdsourced Security Testing道所查關鍵字在表中的位置,從而直接通過下標找到記錄。使ASL趨近與0.
1) 雜湊(Hash)函數是一個映象,即: 將關鍵字的集合映射到某個地址集合上,它的設定很靈活,只要這個地 址集合的大小不超出允許範圍即可;
2) 由於雜湊函數是一個壓縮映象,因此,在一般情況下,很容易產生“衝突”現象,即: key1。=key2,而 f (key1) = f(key2)。
3). 只能盡量減少衝突而不能完全避免衝突,這是因為通常關鍵字集合比較大,其元素包括所有可能的關鍵字, 而地址集合的元素僅為雜湊表中的地址值
在構造這種特殊的“尋找表” 時,除了需要選擇一個“好”(儘可能少產生衝突)的雜湊函數之外;還需要找到一 種“處理衝突” 的方法。
二.Hash建構函式的方法
1.直接定址法:
直接定址法是以資料元素關鍵字k本身或它的線性函數作為它的雜湊地址,即:H(k)=k 或 H(k)=a×k+b ; (其中a,b為常數)
例1,有一個人口統計表,記錄了從1歲到100歲的人口數目,其中年齡作為關鍵字,雜湊函數取關鍵字本身,如圖(1):
| 地址 |
A1 |
A2 |
…… |
A99 |
A100 |
| 年齡 |
1 |
2 |
…… |
99 |
100 |
| 人數 |
980 |
800 |
…… |
495 |
107 |
可以看到,當需要尋找某一年齡的人數時,直接尋找相應的項即可。如尋找99歲的老人數,則直接讀出第99項即可。
| 地址 |
A0 |
A1 |
…… |
A99 |
A100 |
| 年齡 |
1980 |
1981 |
…… |
1999 |
2000 |
| 人數 |
980 |
800 |
…… |
495 |
107 |
如果我們要統計的是80後出生的人口數,如上表所示,那麼我們隊出生年份這個關鍵字可以用年份減去1980來作為地址,此時f(key)=key-1980
這種雜湊函數簡單,並且對於不同的關鍵字不會產生衝突,但可以看出這是一種較為特殊的雜湊函數,實際生活中,關鍵字的元素很少是連續的。用該方法產生的雜湊表會造成空間大量的浪費,因此這種方法適應性並不強。[2]↑
此法僅適合於:地址集合的大小 = = 關鍵字集合的大小,其中a和b為常數。
2.數字分析法:
假設關鍵字集合中的每個關鍵字都是由 s 位元字組成 (u1, u2, …, us),分析關鍵字集中的全體,並從中提取分布均勻的若干位或它們的組合作為地址。
數字分析法是取資料元素關鍵字中某些取值較均勻的數字位作為雜湊地址的方法。即當關鍵字的位元很多時,可以通過對關鍵字的各位進行分析,丟掉分布不均勻的位,作為雜湊值。它只適合於所有關鍵字值已知的情況。通過分析分布情況把關鍵字取值區間轉化為一個較小的關鍵字取值區間。
例2,要構造一個資料元素個數n=80,雜湊長度m=100的雜湊表。不失一般性,我們這裡只給出其中8個關鍵字進行分析,8個關鍵字如下所示:
K1=61317602 K2=61326875 K3=62739628 K4=61343634
K5=62706815 K6=62774638 K7=61381262 K8=61394220
分析上述8個關鍵字可知,關鍵字從左至右的第1、2、3、6位取值比較集中,不宜作為雜湊地址,剩餘的第4、5、7、8位取值較均勻,可選取其中的兩位作為雜湊地址。設選取最後兩位作為雜湊地址,則這8個關鍵字的雜湊地址分別為:2,75,28,34,15,38,62,20。
此法適於:能預先估計出全體關鍵字的每一位上各種數字出現的頻度。
3.摺疊法:
將關鍵字分割成若干部分,然後取它們的疊加和為雜湊地址。兩種疊加處理的方法:移位疊加:將分 割後的幾部分低位對齊相加;邊界疊加:從一端沿分割界來回摺疊,然後對齊相加。
所謂摺疊法是將關鍵字分割成位元相同的幾部分(最後一部分的位元可以不同),然後取這幾部分的疊加和(捨去進位),這方法稱為摺疊法。這種方法適用於關鍵字位元較多,而且關鍵字中每一位上數字分布大致均勻的情況。
摺疊法中數位摺疊又分為移位疊加和邊界疊加兩種方法,移位疊加是將分割後是每一部分的最低位對齊,然後相加;邊界疊加是從一端向另一端沿分割界來回摺疊,然後對齊相加。
例4,當雜湊表長為1000時,關鍵字key=110108331119891,允許的地址空間為三位十進位數,則這兩種疊加情況如圖:
移位疊加 邊界疊加
8 9 1 8 9 1
1 1 9 9 1 1
3 3 1 3 3 1
1 0 8 8 0 1
+ 1 1 0 + 1 1 0
(1) 5 5 9 (3)0 4 4
圖(2)由摺疊法求雜湊地址
用移位疊加得到的雜湊地址是559,而用邊界疊加所得到的雜湊地址是44。如果關鍵字不是數值而是字串,則可先轉化為數。轉化的辦法可以用ASCⅡ字元或字元的次序值。
此法適於:關鍵字的數字位元特別多。
4.平方取中法
這是一種常用的雜湊函數構造方法。這個方法是先取關鍵字的平方,然後根據可使用空間的大小,選取平方數是中間幾位為雜湊地址。
雜湊函數 H(key)=“key2的中間幾位”因為這種方法的原理是通過取平方擴大差別,平方值的中間幾位和這個數的每一位都相關,則對不同的關鍵字得到的雜湊函數值不易產生衝突,由此產生的雜湊地址也較為均勻。
例5,若設雜湊表長為1000則可取關鍵字平方值的中間三位,如圖所示:
| 關鍵字 |
關鍵字的平方 |
雜湊函數值 |
| 1234 |
1522756 |
227 |
| 2143 |
4592449 |
924 |
| 4132 |
17073424 |
734 |
| 3214 |
10329796 |
297 |
下面給出平方取中法的雜湊函數
//平方取中法雜湊函數,結設關鍵字值32位的整數
//雜湊函數將返回key * key的中間10位
Int Hash (int key)
{
//計算key的平方
Key * = key ;