冒险解谜游戏中文网 ChinaAVG

标题: 各种字符串Hash函数比较 [打印本页]

作者: shane007    时间: 2010-5-20 11:30
标题: 各种字符串Hash函数比较
原文
4 h0 q& \0 r" z; z" U. phttp://blog.csai.cn/user3/50125/archives/2009/35638.html 1 U. ^1 x' C( c) w& r( r

5 L6 D3 f  u- o: H4 e[pre]文章转摘自http://www.cmykrgb123.cn/blog/string-hash-compare/ $ z) R+ ?. N3 L/ E7 ^' I+ y
  
! p! m' K% _9 M. t1 I常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法。这些函数使用
! \) e; `9 N3 N8 _& I  v+ x1 `位运算使得每一个字符都对最后的函数值产生影响。另外还有以MD5和SHA1为代表的杂凑函数, 9 q0 c* `6 P  [, F" \) D( q6 z3 S
这些函数几乎不可能找到碰撞。 3 j+ k; S1 Q- t+ K$ Q( F
常用字符串哈希函数有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash, $ J5 v" `7 j7 ]
PJWHash,ELFHash等等。对于以上几种哈希函数,我对其进行了一个小小的评测。 " f6 h, t; M6 a: e
Hash函数数据1数据2数据3数据4数据1得分数据2得分数据3得分数据4得分平均分
BKDRHash20477448196.5510090.9582.0592.64
APHash23475449396.5588.4610051.2886.28
DJBHash22497547496.5592.31010083.43
JSHash14476150610084.6296.8317.9581.94
RSHash10486150510010051.5820.5175.96
SDBMHash32484950493.192.3157.0123.0872.41
PJWHash302648785130043.89021.95
ELFHash302648785130043.89021.95

! g; V2 u- C. A: m5 Z其中数据1为100000个字母和数字组成的随机串哈希冲突个数。数据2为100000个有意义的英文句
2 {/ a7 t. U! l- P9 a; R" E" \子哈希冲突个数。数据3为数据1的哈希值与1000003(大素数)求模后存储到线性表中冲突的个数。
, ?% ?( E0 a; p! V5 ~" p. T5 ^数据4为数据1的哈希值与10000019(更大素数)求模后存储到线性表中冲突的个数。
2 ]  I. q; E5 F- t3 F& k' T经过比较,得出以上平均得分。平均数为平方平均数。可以发现,BKDRHash无论是在实际效果还是
& G* w1 S3 J2 N( E( a! u/ K编码实现中,效果都是最突出的。APHash也是较为优秀的算法。DJBHash,JSHash,RSHash与
/ W" ?5 O5 h9 P$ q9 I/ c; j+ VSDBMHash各有千秋。PJWHash与ELFHash效果最差,但得分相似,其算法本质是相似的。 8 c2 ?1 x5 S* m
在信息修竞赛中,要本着易于编码调试的原则,个人认为BKDRHash是最适合记忆和使用的。 ) z+ t# ?/ X9 M
CmYkRgB123原创,欢迎建议、交流、批评和指正。
6 T' Q5 ~" l5 [* P  
" ?4 j$ ?9 i( w% B' ]- m% T5 _附:各种哈希函数的C语言程序代码
9 U. I1 ]/ s+ f% I- m" R* Q4 E9 D7 Q3 D4 C
unsigned int SDBMHash(char *str) ' r- N) o2 B6 A
{ " s& _7 t2 {4 W3 }; h1 H- B
    unsigned int hash = 0;
! B9 d% G- j$ C9 L' ]9 j/ J# n" D  k) K  # g' t: G; G' E2 y, T: I
    while (*str)
5 a& h/ H+ E  s9 Z    { 0 ~) o1 Y. H# a) t" ~& c
        // equivalent to: hash = 65599*hash + (*str++); 9 I# P% [9 ?- f' |
        hash = (*str++) + (hash << 6) + (hash << 16) - hash; & ]0 J* p) C+ I4 m* b% h% t2 T
    }
+ P% p$ z) u% x1 `- |$ K. u2 I, @  
' z& c1 {! y+ j+ X' U    return (hash & 0x7FFFFFFF);
5 [) p  v" O) r* [7 g} 9 N- D' H- a: c! {
  
4 @" X5 \9 G! O& ~: O' U! {4 t// RS Hash 0 r: O+ ^  h  }5 J" J( ~" e8 s
unsigned int RSHash(char *str)
" D; `8 a( Z; ]' e' p% [{ 4 a# s/ {7 \+ E3 r- T4 M/ E. h
    unsigned int b = 378551; 6 u4 b2 c: A! s* o* B8 \% J2 P* `6 Z
    unsigned int a = 63689;
1 h- e- |, w; b. Z# e8 U    unsigned int hash = 0;
5 z5 ^; K) ]7 |* v3 J, F5 Z  % p- Z: g) ]) V% y
    while (*str) + j& q3 J8 Y  T4 @; p4 R+ `
    {
- W8 k1 ^0 W1 W' L( j' }+ g        hash = hash * a + (*str++); ; K4 x" M/ H! [8 t
        a *= b;
% k' F6 s6 O; n1 e9 B& E1 d    }
4 B) N8 a7 c7 U& S7 y! \4 f8 E  * o2 t2 A7 r7 Q( I
    return (hash & 0x7FFFFFFF); " e( x. c2 R' k7 v6 l
} ( b" l  I4 p) ~" L
  ) M, R1 }' Y/ w4 f
// JS Hash # {- T$ Z; I4 z& d
unsigned int JSHash(char *str)
! W# ^( E0 Q- N! y& P5 b{
5 @' G" j& B9 [    unsigned int hash = 1315423911; : n4 Y4 f$ y8 S# e/ I% k5 r
  
! b# o& k& z; e/ `: R0 p    while (*str) ' D7 G" `8 V# X* p3 s$ ?; G
    { 1 j( d5 D+ X; O$ t/ G5 u* R* S
        hash ^= ((hash << 5) + (*str++) + (hash >> 2));
3 K1 Y1 R: a, o3 o    } : z3 \* J, Q" w6 ?. Y
  ! D0 X  i8 [/ J
    return (hash & 0x7FFFFFFF);
: k( E& k7 j- t}
' x0 h% H( }. Z3 J! E  
+ V# E) Z) B! X" F3 u// P. J. Weinberger Hash
$ h( S- ]& j0 C  Y2 A  d# yunsigned int PJWHash(char *str)
% `! q- \8 O+ i6 n{8 J1 s! ~  I1 x! g
    unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);" s; y: W! e6 |9 f9 D) b
    unsigned int ThreeQuarters    = (unsigned int)((BitsInUnignedInt  * 3) / 4);& t/ ?% ~# z: U* X: A
    unsigned int OneEighth = (unsigned int)(BitsInUnignedInt / 8);. w. X9 k( s0 i9 X; D. ~
    unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnignedInt [pre]                                               - OneEighth);    unsigned int hash    = 0;    unsigned int test    = 0;     while (*str)    {        hash = (hash << OneEighth) + (*str++);        if ((test = hash & HighBits) != 0)        {            hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));        }    }     return (hash & 0x7FFFFFFF);} // ELF Hash unsigned int ELFHash(char *str){    unsigned int hash = 0;    unsigned int x    = 0;     while (*str)    {        hash = (hash << 4) + (*str++);        if ((x = hash & 0xF0000000L) != 0)        {            hash ^= (x >> 24);            hash &= ~x;        }    }     return (hash & 0x7FFFFFFF);} // BKDR Hash unsigned int BKDRHash(char *str){    unsigned int seed = 131; // 31 131 1313 13131 131313 etc..    unsigned int hash = 0;     while (*str)    {        hash = hash * seed + (*str++);    }     return (hash & 0x7FFFFFFF);} // DJB Hash unsigned int DJBHash(char *str){    unsigned int hash = 5381;     while (*str)    {        hash += (hash << 5) + (*str++);    }     return (hash & 0x7FFFFFFF);} // AP Hash unsigned int APHash(char *str){    unsigned int hash = 0;    int i;     for (i=0; *str; i++)    {        if ((i & 1) == 0)        {            hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));        }        else        {            hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));        }    }     return (hash & 0x7FFFFFFF);}[/pre]





欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/) Powered by Discuz! X3.2