文字列Hash関数の比較


                     hash  ,     ,        ,    :
 
 
 
 
 
 
//@brief BKDR Hash Function//@detail本アルゴリズムはBrian KernighanとDennis Ritchの『The C Prograamming Language』という本が展示されていることから名付けられました。簡単で速いhashアルゴリズムであり、Javaが現在採用している文字列のHashアルゴリズムです。templatesize_t BKDRHash(const T*str){register size hash=0;while(sizeut ch=(sizaut)*str+){hash=hash*131+ch;/31、131、1313、13131331、13131313を乗じてもいいです。/乗算をビット演算に分解したり、減算したりすると効率が上がると言われています。上式をhash=hashと表現すると、<7+hash+ch;/実はIntelプラットフォームでは、CPU内部の処理効率は100億回以上です。計算すると、両者の時間差は基本的に0であることが分かります。(Debug版であれば、ビット演算に分解した場合は、1/3高くなります。);/ARMのようなRISCシステムではテストしたことがないので、ARM内部ではBooth's Algorithmを使って32ビットの整数乗算をシミュレートしています。その効率は乗数に関係しています。/乗数8-31ビットが1または0の場合、1クロック周期が必要です。/乗数16-31ビットが全部1または0の場合、2クロック周期が必要です。4つのクロック周期を必要とします。だから、私は実際にテストしていませんが、効率的にはあまり差がないと思います。BKDRHashと思想が一致していることから名付けられました。ただ種が違っています。templatesize_SDBMsh_sh(const T*str)。//@brief RS Hash Function///@detailはRobert Sedgwicksがその『Algorithms in C』の本に展示されていることから名付けられました。template<class T>sizzzash(const-str){registststststzzash=0;sizzzzzzzzzazzzzazzzzzzzzzzazzzzzzzzzzzzzzzzzzzazzzzzzzzzzzzzzzzzazzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzreturn hash;///@brief AP hash Function///@detailは、Arash Patowによって発明されたhashアルゴリズムである。template<class T>sizzzzash(const*str){registstststststs==0;sizzatch;for(long=0=0)(long=0===0;ch=====================================================================================}else{hash^=(~)(((<<11)^ch^(hash>>5))}return hash;justiin Sobelによって発明されたhashアルゴリズムです。templatesizzzzzzzaut(const T*str){if(!str)//これは本人が追加して、空の文字列がハッシュ値0 return 0に戻ることを保証します。register sizeze=======================================================================================================sh>>>>2);リターンsh;このアルゴリズムは、Donnald E.Knuthが『Art Of CoputterProgramming Volume 3』に展示されていることから名付けられたものです。template<class T>sizzeKHash(const T*str){if(!str)/これは、本人がハッシュ値を追加して返します。*str++){hash=((hash<<5>>>27)^ch;/@return hash;/@brienf FNV Hash Fnction///@detail Unix systemシステムで使用される有名なhashアルゴリズムは、その後、マイクロソフトもそのhash umapで実現されます。これは本人が追加したもので、空文字列がハッシュ値0に戻ることを保証するために、registster sizzehash=21661366261;while(sizzauth=(sizzaut)*ststr+){hash*=16777619;hash^h==========>haturnhash hash hash hash;;;///@@briturnhaturnhash hash hash hash hash hash hash;//@@@breturnhaturnhaturnhash@@brieezzzzzzzzzzzzzzzzzzzzeeeeeee( const T*str){ifこれは本人が追加したもので、空文字列がハッシュ値0 return 0に戻ることを保証します。registster sizauthash=5381;while(sizzauth=(sizzaut)* str+){hash+=(hash<5)+ch;;;)returnhash hash;/////@brief/brerededejjjjjjjjjeceezeef/BBBBBBBBBBBBBBBdededededededededededenjjjjjjjjjjjjjjjjjjjjjjjjjjjjjeeeeeeeeeeeeeB 2 Hash(const T*str){if(!*str)//これは本人が追加して、空の文字列がハッシュ値0 return 0に戻ることを保証するためです。register size hash=5381;while(size tuch=(size tu)*str+){hash=hash*33 ch;return hash;//@brief PJW Hash Function//@detail本アルゴリズムはAT&Tベル実験室のPeter J.Weinbergerの論文に基づいて発明されたhashアルゴリズムです。templatesizePJWHsh(const-str){static const sizaut Total Bits 3=Thesits 3。4;static const sizzzzaut OneEighh=TotalBits/8;static const sizaut HighBits=((sizaut)-1)<(TotalBits-OneEighhh);registststststststststitit sizzzash= 0;sizutmagic=0=0;sizzze=0;sizzzzzzeeeeeeeeze=0=========0;wzzzzzzzzzzzzzzzzzzzzeeeeeeeeeeeeeeeeeeeeeeeeiiiiiize ghBits!=0){hash=((magic>>ThreeQuarts)/(~HighBits)}return hash;///@brief EEEEEEEEELF hashFFnction//@detailはUnixのExteded LibrararyFnctionに添付されたことから名付けられたhashアルゴリズムです。これはPJW Hashの変形です。templatesizutELFsh ELFsh(const ststststit ELFFsh=const=stststststitititit=stststststststststststststststststititititit=stststststststststititititititititititititititititititititititititit=ststst3)4;static const sizzzzaut OneEighh=TotalBits/8;static const sizaut HighBits=((sizaut)-1)<(TotalBits-OneEighhh);registststststststststitit sizzzash= 0;sizutmagic=0=0;sizzze=0;sizzzzzzeeeeeeeeze=0=========0;wzzzzzzzzzzzzzzzzzzzzeeeeeeeeeeeeeeeeeeeeeeeeiiiiiize ghBits)!==0){hash^=(magic>>ThreeQuares;hash=~magic;}return hash; 
これらのhashのハッシュ品質と効率について簡単なテストを行いました。テスト結果は以下の通りです。
テスト1:1000個の大きさ文字と数字でランダムなANSI文字列(重複なし、各文字列の最大長さは64文字を超えない)に対してハッシュを行います。
文字列関数
衝突の数
100003を除いた後の衝突数
BKDRHash
0
4826
SDBMHash
2
4814
RSHash
2
4886
APhash
0
4846
ELFHash
1515
6120
Jshas
779
5587
DEKHash
863
5643
FNVHash
2
4872
DJ Bhash
832
5645
DJ 2 Hash
695
5309
PJWHAS
1515
6120
 
テスト2:1000個のユニコムからなる任意の文字列(重複なし、各文字列の最大長さは64文字を超えない)に対してハッシュを行います。
文字列関数
衝突の数
100003を除いた後の衝突数
BKDRHash
3
4710
SDBMHash
3
4904
RSHash
3
4822
APhash
2
4891
ELFHash
16
4869
Jshas
3
4812
DEKHash
1
4755
FNVHash
1
4803.
DJ Bhash
1
4749
DJ 2 Hash
2
4817
PJWHAS
16
4869
 
テスト3:1000個のランダムANSI文字列(重複なし、各文字列の最大長さは64文字を超えない)をハッシュする:
文字列関数
所要時間(ミリ秒)
BKDRHash
109
SDBMHash
109
RSHash
124
APhash
187
ELFHash
249
Jshas
172
DEKHash
140
FNVHash
125
DJ Bhash
125
DJ 2 Hash
125
PJWHAS
234
 
結論:私のサンプルにはいくつかの特殊性があるかもしれません。ASCIIコード文字列をハッシュする時、PJWとELF Hash(実は同じアルゴリズムです。)は品質でも効率でもかなり悪いです。「この2つの文字列はPJWでハッシュされたhash値と同じです。また、他のいくつかは、JS/DEK/DJB Hashなどのハッシュ関数に依存しています。アルファベットと数字からなる文字列のハッシュ効果もあまり良くないです。BKDRとSDBMのような簡単なHash効率と効果がいいです。
その他:
著者:icefireelf
出典:http://blog.csdn.net/icefireelf/article/details/5796529