雜湊 雜湊函式 衝突處理

2021-08-04 23:05:23 字數 3393 閱讀 2135

!!!例:如果我們現在要統計的是80後出生年份的人口數,那麼我們對出生年份這個關鍵字可以用年份減去1980來作為位址。

此時f (key) = key-1980。

這樣的雜湊函式優點就是簡單、均勻,也不會產生衝突,但問題是這需要事先知道關鍵字的分布情況,適合查詢表較小且連續的情況。由於這樣的限制,在現實應用中,直接定址法雖然簡單,但卻並不常用。

(4)、平方取中法

如: 56793542

56793542

x 56793542

—————————

3225506412905764

h(56793542) = 641

取中間的四位

平方取中法的目的:根摺疊法是一樣的,都是讓結果受更多位數的影響。

(5)、除留餘數法:此方法為最常用的構造雜湊函式方法。對於雜湊表長為m的雜湊函式公式為:f( key ) = key mod p ( p ≤ m )。

mod是取模(求餘數)的意思。事實上,這方法不僅可以對關鍵字直接取模,也可在摺疊、平方取中後再取模。

例:

不過這也是存在衝突的可能的,因為12 = 2×6 = 3×4。如果關鍵字中有像18(3×6)、30(5×6)、42(7×6)等數字,它們的餘數都為6,這就和78所對應的下標位置衝突了。

!!!如何合理選取p值

使用除留餘數法的乙個經驗是,若雜湊表表長為m,通常p為小於或等於表長(最好接近m)的最大質數或不包含小於20質因子的合數。

這句話怎麼理解呢?

我再舉個例子:某雜湊表的長度為100,雜湊函式h(k)=k%p,則p通常情況下最好選擇哪個呢?a、91 b、93 c、97 d、99

實踐證明,當p取小於雜湊表長的最大質數時,產生的雜湊函式較好。我選97,因為它是離長度值最近的最大質數。

typedef

unsigned

int index;

index hash(const

char *key,int size)

return hashval % size;

}

衝突嚴重:a3、b2、c1;eat、 tea;

(2)、簡單的改進——前3個字元移位法

h(key)=(key[0]*27*27 + key[1]*27 + key[2])mod tablesize

typedef unsigned int index;

index hash(const char *key,int size)

仍然衝突:string、 street、strong、structure等等;

空間浪費:3000/263 ≈ 30%

index hash ( const

char *key, int tablesize )

這個跟上面公式是一樣的,但是乘法次數明顯少很多,計算速度更快。

 若發生了第 i 次衝突,試探的下乙個位址將增加di,基本公式是:

hi(key) = (h(key)+di) mod tablesize ( 1≤ i < tablesize )

!!!di 決定了不同的解決衝突方案:線性探測(di = i)、平方探測(di = i*i)、雙雜湊(di = i*h2(key))。

例:我們的關鍵字集合為,表長為12。 我們用雜湊函式f(key) = key mod l2。

當計算前s個數時,都是沒有衝突的雜湊位址,直接存入:

計算key = 37時,發現f(37) = 1,此時就與25所在的位置衝突。於是我們應用上面的公式f(37) = (f(37)+1) mod 12 = 2。於是將37存入下標為2的位置。

接下來22,29,15,47都沒有衝突,正常的存入。

到了 key=48,我們計算得到f(48) = 0,與12所在的0位置衝突了,我們f(48) = (f(48)+1) mod 12 = 1,此時又與25所在的位置衝突。於是f(48) = (f(48)+2) mod 12=2,還是衝突……一直到 f(48) = (f(48)+6) mod 12 = 6時,才有空位,趕快存入。存入完的結果:

從這個例子我們也看到,我們在解決衝突的時候,還會碰到如48和37這種本來都不是同義詞卻需要爭奪乙個位址的情況,我們稱這種現象為堆積。很顯然,堆積的出現,使得我們需要不斷處理衝突,無論是存入還是查詢效率都會大大降低。

(2)、分離鏈結法:將所有關鍵字為同義詞的記錄儲存在乙個單鏈中,我們稱這種表為同義詞子表,在雜湊表中只儲存所有同義詞子表的頭指標。

對於關鍵字集合,我們用前面同樣的12為除數,進行除留餘數法:

此時,已經不存在什麼衝突換址的問題,無論有多少個衝突,都只是在當前位置給單鏈表增加結點的問題。很不錯的解決思路。

分離拉鍊法解決衝突的做法是:將所有關鍵字為同義詞的結點鏈結在同乙個單鏈表中。若選定的雜湊表長度為m,則可將雜湊表定義為乙個由m個頭指標組成的指標陣列t[0..m-1]。凡是雜湊位址為i的結點,均插入到以t[i]為頭指標的單鏈表中。t中各分量的初值均應為空指標。在拉鍊法中,裝填因子α可以大於 1,但一般均取α≤1。

拉鍊法的優勢與缺點

與開放定址法相比,拉鍊法有如下幾個優點:

(1)拉鍊法處理衝突簡單,且無堆積現象,即非同義詞決不會發生衝突,因此平均查詢長度較短;

(2)、由於拉鍊法中各煉表上的結點空間是動態申請的,故它更適合於造表前無法確定表長的情況;

(3)、開放定址法為減少衝突,要求裝填因子α較小,故當結點規模較大時會浪費很多空間。而拉鍊法中可取α≥1,且結點較大時,拉鍊法中增加的指標域可忽略不計,因此節省空間;

(4)、在用拉鍊法構造的雜湊表中,刪除結點的操作易於實現。只要簡單地刪去鍊錶上相應的結點即可。而對開放位址法構造的雜湊表,刪除結點不能簡單地將被刪結 點的空間置為空,否則將截斷在它之後填人雜湊表的同義詞結點的查詢路徑。這是因為各種開放位址法中,空位址單元(即開放位址)都是查詢失敗的條件。因此在用開放位址法處理衝突的雜湊表上執行刪除操作,只能在被刪結點上做刪除標記,而不能真正刪除結點。

拉鍊法的缺點:指標需要額外的空間,故當結點規模較小時,開放定址法較為節省空間,而若將節省的指標空間用來擴大雜湊表的規模,可使裝填因子變小,這又減少了開放定址法中的衝突,從而提高平均查詢速度。

雜湊表 雜湊函式構建和衝突處理

雜湊法又稱雜湊法 雜湊法以及關鍵字位址計算法等,相應的表稱為雜湊表。基本思想是 首先在元素的關鍵字k和元素的儲存位置p之間建立乙個對應關係f,使得p f k f稱為雜湊函式。建立雜湊表時,把關鍵字為k的元素直接存入位址為f k 的單元 以後當查詢關鍵字為k的元素時,再利用雜湊函式計算出該元素的儲存位...

雜湊表 雜湊函式 雜湊衝突與解決

雜湊表 通過關鍵碼來對映到值的乙個資料結構 雜湊函式 鍵與值對映的乙個對映關係 常用方法 1 直接定址法 f x kx b k b都是常數 一旦確定了雜湊函式,那麼新增 獲取元素都需要通過這個雜湊函式 2 除留餘數法 f x x k k是常數,k m m為儲存位置長度 其他幾種方法 方法名說明 適合...

雜湊表,雜湊衝突

什麼是雜湊表?雜湊表 hash table,也叫雜湊表 是根據關鍵碼值 key value 而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中乙個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表。關鍵字 雜湊函式 雜湊函式 雜湊位址 優點 一對一的查詢...