[爆卦]hash function範例是什麼?優點缺點精華區懶人包

為什麼這篇hash function範例鄉民發文收入到精華區:因為在hash function範例這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者FRAXIS (喔喔)看板C_and_CPP標題[心得] Bit index和de Bruijn...


以前上課的時候老師有提過這個問題,這些是當時的筆記,我覺得最後

的解法蠻有趣的,跟大家分享。


假定有一個非零正數x以二進位表示,要找出最後一個1的位置,範例:

0100101000100000 <- 第 6 個位置為1,所以輸出 5

(計算0-base的位置,也可以想像成是算最後有幾個0)

在這邊先假設n為機器上表示一個整數所使用的位元數,以n=32來示範。

首先可以把題目簡化,假定x中只有一個bit為1,如果x中有兩個以

上的bit為1,可以利用 x &= (~x+1)來把最後一個1分離。

(x &= -x也可以,如果是二的補數表示法)

當分離出來之後,就有很多種計算法了,這邊就不考慮用組合語言的解法。

第一種是迴圈法

for ( index = -1; x > 0; x >>= 1, ++index ) ;

不過這種方法會需要n次的計算。

第二種是二分搜尋法,這需要lg n次的比較。

第三種方法是用bitwise parallel的技巧,其實跟二分搜尋法是一樣的道理

index = 0;
index += (!!(x & 0xAAAAAAAA)) * 1;
index += (!!(x & 0xCCCCCCCC)) * 2;
index += (!!(x & 0xF0F0F0F0)) * 4;
index += (!!(x & 0xFF00FF00)) * 8;
index += (!!(x & 0xFFFF0000)) * 16;

雖然需要lg n次的計算,但是不像二分搜尋法要做比較運算。

第四種方法是查表,不過x的範圍很大,所以只能分段查表。

第五種方法是利用perfect hash的技巧。

因為x只有32種可能,可以設計一個perfect hash function直接查

出index。

而這個hash function一般會用 x % 37,同時需要開一個大小為37

的table(所以有一些空間會浪費了)。

這方法很好設計,就是找比n稍微大一點的數字來試試看即可。


第六種是利用de Bruijn sequence。

其實這方法跟第五種方法很像,也是設計一個perfect hash function。

只是這方法免除了取餘數的運算,同時也只需要大小為32的table。

hash function是 (x * 0x077CB531) >> 27 其中的0x077CB531就是

de Bruijn sequence。

這方法對於n是二的次方數的機器都可以使用,至於n不是二的次方數

的機器應該不多。

這方法的原理從兩個方面來看,第一個是x本身一定是二的次方數,

所以任何一個數字乘以x,就相當於左移的運算。

而de Bruijn sequence的特殊之處,就是在於此序列中的任意連續

五位元都是相異的。五個位元總共有三十二種可能性,而至少要有

三十二個位元才有可能包含所有三十二種可能性(序列要想成頭尾

相接的)

舉例:00010111就包含了 000, 001, 010, 101, 011, 111, 110, 100

這八種三位元的所有組合。

所以當de Bruijn sequence乘以 x 又右移27個位元的時候,就相

當於是把sequence中的一組五位元子序列取出,這保證不同的x一

定會有不同的子序列,所以是一個很好的hash函數。

(32位元的de Bruijn sequence有很多個,但是這方法要用的時候
必須挑00000開頭的)


關於第六種方法的詳細研究可以參考下面這網址,裡面還有說當一
個數字有兩個bit為1的時候,怎樣可以快速找出來
http://supertech.csail.mit.edu/papers/debruijn.pdf

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.119.162.51

你可能也想看看

搜尋相關網站