天天看點

哈希表的C實作(一)

哈希表在像Java、C#等語言中是與生俱來的。可是在C的世界中,似乎隻有自己動手,豐衣足食;在網上google了一把,大緻有幾個版本,我會一一來分析對比;

首先先來交代一下哈希表實作中需要注意的一些概念:

哈希函數

也叫散列函數,即:根據key,計算出key對應記錄的儲存位置

position = f(key)

散列函數滿足以下的條件:

1、對輸入值運算,得到一個固定長度的摘要(Hash value);

2、不同的輸入值可能對應同樣的輸出值;

以下的函數都可以認為是一個散列函數:

f(x) = x mod 16; (1)

f(x) = (x2 + 10) * x; (2)

f(x) = (x | 0×0000FFFF) XOR (x >> 16); (3)

不過,僅僅滿足上面這兩條的函數,作為散列函數,還有不足的地方。我們還希望散列函數滿足下面幾點:

1、散列函數的輸出值盡量接近均勻分布;

上面兩點用數學語言表示,就是:

1, 輸出值y的分布函數F(y)=y/m, m為散列函數的最大值。或記為y~U[0, m]

2,|df(x)/dx| >> 1;

從上面兩點,大家看看,前面舉例的三個散列函數,哪個更好呢?對了,是第三個:

f(x) = (x | 0×0000FFFF) XOR (x >> 16);

它很完美地滿足“好的散列函數”的兩個附加條件。

2、哈希沖突(Hash collision)

也就是兩個不同輸入産生了相同輸出值的情況。首先,哈希沖突是無法避免的,是以,雜湊演算法的選擇直接決定了哈希沖突發送的機率;同時必須要對哈希沖突進行處理,方法主要有以下幾種:

1, 鍊位址法

鍊位址法:對Hash表中每個Hash值建立一個沖突表,即将沖突的幾個記錄以表的形式存儲在其中

2, 開放位址法

下面就來看看每種方法的具體實作吧:

鍊位址法:

舉例說明: 設有 8 個元素 { a,b,c,d,e,f,g,h } ,采用某種哈希函數得到的位址分别為: {0 , 2 , 4 , 1 , 0 , 8 , 7 , 2} ,當哈希表長度為 10 時,采用鍊位址法解決沖突的哈希表如下圖所示。 

哈希表的C實作(一)
哈希表的C實作(一)
哈希表的C實作(一)

(未完待續)

繼續閱讀