hash表
hash表作為一種動態集合資料結構,一般只支援:插入、查詢、刪除操作;而且每個操作的時間複雜度一般控制在o(1)內。
hash表是普通陣列的一種推廣。因為陣列可以在直接通過下標來定位要查詢的元素,時間為o(1)。因此hash表目標也是使用一些技術,以達到可以在o(1)的時間內完成操作。(嚴格來說時間是和裝載因子a相關的)
hash的方法。
1. 直接定址法
前提:關鍵字的全域u比較小;且無重複關鍵字。
方法:關鍵字的全域為。m不是太大,或者可以不考慮記憶體限制;則使用乙個陣列t[0,m-1],每乙個槽代表乙個關鍵字,如果沒有關鍵字對應到槽k,則t[k] = null。
缺點:
關鍵字的全域不能太大;
如果實際關鍵字的數量和關鍵字的全域的數量相比,比較小時,則分配的t有些浪費空間。
2. hash表
為了解決直接定址的缺點,從而產生hash表。
hash表的空間為實際關鍵字的數量階的,o(|k|);與直接定址比缺點在於查詢時間o(1)為平均時間,而直接定址最壞情況也為o(1).
方法:hash表使用乙個hash函式h,以key為引數來計算儲存位置。hash函式h為關鍵字全域u到儲存域m的對映。一般u都比m大,以便達到降低儲存空間的目的,因此對映不為單射。由此,兩個key可能對映到同乙個位置,這時稱為發生碰撞。
3.解決碰撞的方法:
把值相同的元素用乙個鍊錶來表示。插入在鍊錶的頭部插入。
裝載因子:裝載因子為hash表中每乙個槽平均存放的元素個數。可以大於、小於、等於1。
簡單一直雜湊:所有元素均勻雜湊到hash表的m個槽位,而且與已經雜湊的情況無關。
缺點:最壞情況下雜湊到乙個槽,這時相對於鍊錶。
時間:裝載因子為a的簡單一直雜湊,則查詢(成功、失敗)的平均時間為o(1+a)。
結果的計算,失敗要找到尾部;成功則需要使用指示隨機變數來計算。
從這個結果可知,如果hash表的槽位數和存放的元素為同階的,即n=o(m)。從而a=n/m=o(1),則hash表的查詢為o(1)的。
3.2. 開放定址法
在插入的過程中,如果有衝突,則會繼續查詢,直到找到乙個空的槽位為止。
探測:衝突時,查詢空槽的過程稱為探測。
與普通hash比,探測需要探測號,探測了幾次。因此比一般的hash多乙個引數。
而且如果表有空槽,則一定會探測到。
因此:h(k,i)對每乙個k來說,h(k,0),h(k,1),…,h(k,m-1)必須為0,1,….,m-1的乙個排列。否則某個位置就不能被探測到。
探測方法
3.2.1. 線性探測
線性探測中,有乙個輔助雜湊函式。或者稱為h(k,0)。
h(k,i)=(h(k,0)+i) mod m
即第一次探測為h(k,0),如果非空,則找h(k,0)+1,直到找到空位置。
缺點:存在稱為一次群集的問題,如果對於不同的k1,k2,如果h(k1,0)和h(k2,0)相同,則所有的探測順序都相同。即隨著時間的推移,連續的槽被占用的情況會增加,從而查詢也會增加開銷。
3.2.2. 二次探測
二次探測是使用二次函式來做探測。也有乙個輔助雜湊函式。或者稱為h(k,0)。
h(k,i)=(h(k,0)+c1*i+c2*i^2) mod m
c1,c2為輔助常數。初始探測也為h(k,0)。之後的探測不是線性的查詢空槽,而是有偏移量的查詢空槽偏移量為探測次數的二次函式。
缺點:
和線性探測相同,也有群聚的現象。對於不同的k1,k2,如果h(k1,0)和h(k2,0)相同,則後續的探測都會相同。因此也會產生群聚,這種群聚稱為二次群聚。
另外,為了提高hash表的利用率,c1,c2,m的選擇有一些限制。
3.2.3. 雙重雜湊(二次hash)
雙重雜湊使用兩個輔助函式來進行雜湊計算。h1(k),h2(k)。
h(k,i)=(h1(k)+i*h2(k)) mod m
為了探測到整個表,h2(k)有一些限制。一種方法是取m為2的冪次,並使得h2只生成奇數。或者取m為質數,h2產生的數都比m小。
通常,雙重雜湊的探測序列有o(m^2)種順序,比一次和二次探測的o(m)種順序多,從而與一致雜湊比較接近。
3.2.4. 開放定址的複雜度分析
首先開放定址的裝載因此a<=1。
開放定址一般假設為一致雜湊。
查詢不成功:的次數期望為1/(1-a)。證明使用事件序列,且都探測失敗。hash表半滿,則為2次;為90%滿,則次數為10次。因此如果太滿,則查詢失敗的次數將急劇增加。
插入元素:需要的探測次數的期望為1/(1-a)。因為插入需要做一次查詢不成功的探測。
查詢成功:的次數期望至多為(1/a)*ln(1/(1-a))。比如:hash表為半滿的,則查詢成功的期望為1.3次左右;hash表為90%滿的,則期望為2.5次左右。
4. hash函式
比較好的雜湊函式是盡可能的滿足簡單一直雜湊的條件。
4.1. 除法雜湊
使關鍵字對m取餘。
選擇的限制:m應該選擇質數,且不要接近為2的冪次的數,或10的冪次。
不為2的冪次是因為,k對2的冪次取餘相當於取k的低位,而將高位忽略了。
不為2的冪次減一(如:2^p-1)是因為,如果字元按2^p為基數來解釋,則字元相同,但順序不同的字串可以對映到同樣的鍵。
4.2. 乘法雜湊
選取固定的關鍵字0h(k)=[m*(kamod1)]----1式
含義為關鍵字乘上a後取小數部分,再與m相乘(即hash表的長度),取整即可。
乘法的優點是對m沒有要求,因此一般選擇m為2的冪次。
特別:計算機乙個位元組為w個bit位。hash表的表長m=2^r。則1式可表示為
h[k] = ((a*k)mod(2^w))>>(w-r)----2式
a一般取值在(2^(w-1),2^w)之間。
一般取1式中的a接近**分割值。
在2式中,w,r一般為事先已知(w為位元組位數,r為hash表的位數),從而只需要選擇a值即可將h確定下來。
2式可以理解為:將a表示為二進位制的分數,k乘上a後取小數部分,並取小數部分的最高r位(即向右移動w-r位的整數)。
也可以理解為:將圓圈等分為m份,即hash表的長度;hash函式為在圓上轉動k次,每次轉動a個格仔,最終停下來的地方即為hash函式的結果值。
1式和2式中只有乘法和對2的冪次取餘,對2的冪次取餘屬於移位操作,因此比除法要節約時間。
資料結構 hash
雜湊表 hash table,也叫雜湊表 是根據鍵 key 而直接訪問在記憶體儲存位置的資料結構。分為兩個步驟 hash函式 通過乙個關於鍵值的hash函式,得到所查詢的資料對映到表中乙個位置。訪問資料 不同的key 經過hash函式 可能計算得到相同的輸出。此時叫做衝突,衝突的資料又成乙個表。一般...
資料結構 資料結構之二分查詢
先上 二分查詢,陣列必須為有序的 int binarysearch int key,int a,int length return 1 該函式接受乙個整數鍵和乙個已經有序的int陣列及陣列的大小作為引數。如果該鍵存在於陣列中則返回它的索引,否則返回 1.演算法使用兩個變數lo和hi,並保證如果鍵在陣...
資料結構之hash
hash表 雜湊表 hash table,也叫雜湊表 是根據key而直接進行訪問的資料結構。也就是說,它通過把key對映到表中乙個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表。以資料中每個元素的關鍵字k為自變數,通過雜湊函式h k 計算出函式值,以該函式值作為...