冒险解谜游戏中文网 ChinaAVG

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

作者: shane007    时间: 2010-5-20 11:30
标题: 各种字符串Hash函数比较
原文 6 z7 f) s8 z, @1 L8 o+ k. C4 S
http://blog.csai.cn/user3/50125/archives/2009/35638.html
, K6 p& L( z# O1 {2 V; {: q7 t( z  p$ t4 Q. [7 J* L
[pre]文章转摘自http://www.cmykrgb123.cn/blog/string-hash-compare/
7 O& |8 D8 Q& C  v8 A# o  ' f! q4 n& o5 U& |9 r' j0 D
常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法。这些函数使用 , G2 D, R, u3 P; O! l
位运算使得每一个字符都对最后的函数值产生影响。另外还有以MD5和SHA1为代表的杂凑函数,
" R+ F7 m" a$ _+ f: ?/ [' c7 a这些函数几乎不可能找到碰撞。
6 w5 x: ~6 }! r8 U常用字符串哈希函数有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash,
" h( d- Z  h% P! ]; CPJWHash,ELFHash等等。对于以上几种哈希函数,我对其进行了一个小小的评测。
+ X) V% J- A# \
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

4 \  \1 \0 e' n  g/ b: X3 @其中数据1为100000个字母和数字组成的随机串哈希冲突个数。数据2为100000个有意义的英文句 ( _/ d' G+ B0 J% W
子哈希冲突个数。数据3为数据1的哈希值与1000003(大素数)求模后存储到线性表中冲突的个数。 ) l0 C9 c2 E! ~" S1 x' a
数据4为数据1的哈希值与10000019(更大素数)求模后存储到线性表中冲突的个数。
6 }/ X1 V9 o5 K& K3 g% q经过比较,得出以上平均得分。平均数为平方平均数。可以发现,BKDRHash无论是在实际效果还是 + ^9 c2 X6 b0 c1 L
编码实现中,效果都是最突出的。APHash也是较为优秀的算法。DJBHash,JSHash,RSHash与
3 q: |4 E, e& ~9 j. Q0 P$ D$ V- ZSDBMHash各有千秋。PJWHash与ELFHash效果最差,但得分相似,其算法本质是相似的。
* J! @& @/ g% b* \1 H) v  u在信息修竞赛中,要本着易于编码调试的原则,个人认为BKDRHash是最适合记忆和使用的。 1 B' Y" q0 Y+ |$ r
CmYkRgB123原创,欢迎建议、交流、批评和指正。
/ ~" H: {* q% @: c, T& R: Q  
7 L( r* C0 P! G; E8 I附:各种哈希函数的C语言程序代码
$ I0 I" G0 K! w1 X4 U
) i4 B% A* u2 F  Wunsigned int SDBMHash(char *str) # l7 k8 @. C+ e( I" B) S
{ " @$ n( I1 c  A4 Z9 w
    unsigned int hash = 0; ; F/ c7 z" |; f/ W8 B& _
  , ~$ n: J7 R: f) x1 q
    while (*str)
6 Z2 c" |* {1 F6 Q! R" U7 q    {
3 f1 }. A; q; S  ~        // equivalent to: hash = 65599*hash + (*str++);
( x: S- C5 u! b0 D1 X5 F        hash = (*str++) + (hash << 6) + (hash << 16) - hash;
7 d# p4 E9 J+ X+ `* [8 q    } : \& ]5 q# V  p' P9 V. j5 u$ H
  2 s% O( n1 F3 D9 r
    return (hash & 0x7FFFFFFF); ) N  A3 b7 h, t
} , |0 r% R0 Z  @* V4 c% K
  
/ u9 r" G- R4 V3 J( X6 c8 k/ G7 I// RS Hash 0 t& R/ ]# j. Q7 \
unsigned int RSHash(char *str)
6 \% x  k4 \& E. F{ & A* ~8 ?) |2 m' B0 t. h# e6 R
    unsigned int b = 378551;
* c" C: [  L6 F( P0 i    unsigned int a = 63689;
# b, ^0 E3 d9 d+ I" j0 e6 c+ }    unsigned int hash = 0; & k9 N( R; i+ O* @
  / C( Y; d8 ]  T& e& t' ?
    while (*str)
, L! a& d6 N2 e# c    { ; L  U2 `+ A  C- z! P
        hash = hash * a + (*str++); 7 A( V8 g' w( N) @! x
        a *= b; & ~9 U1 s' @& |5 e" E+ `% C6 Q- x
    } " s$ `8 F8 ^$ H6 O( A  L
  1 t9 [  ^4 p3 \) I1 N- f
    return (hash & 0x7FFFFFFF);
8 ?% {: e. V8 @- H} ' I; \! o" Y- i. R! ^! f8 f
  
; j5 m; E: f* h; a+ r) l- p// JS Hash
7 x5 p& Y8 L4 F: j. ?unsigned int JSHash(char *str)
( g/ h# r' p6 F0 O. f: a4 ^{ 9 p7 m, j  W4 R0 U3 j! E, \3 K
    unsigned int hash = 1315423911;   s. ^  d9 |6 q. N/ }0 J
  , j8 v7 \0 m3 @4 M+ Z: M
    while (*str)
( _3 M0 p3 T- t! w- X! V3 M$ k1 Y8 E: L    { 4 @7 ~# x7 a# C3 E1 J
        hash ^= ((hash << 5) + (*str++) + (hash >> 2)); 4 N' B/ W- R- y3 i+ d- K" x
    }
% l/ x( n, Z' `, o" V% |& v( l7 e  b  
( G" u( D6 M* f/ Q/ i1 S    return (hash & 0x7FFFFFFF); - n& w" K3 E7 g/ ?! s& Y3 |* [
}
1 B0 a; M9 w$ [3 [  
) f7 N% q1 `6 ~// P. J. Weinberger Hash
7 q+ j3 Y" Q1 E* E3 hunsigned int PJWHash(char *str)" Q4 j6 t: Y5 Z( b
{7 G7 W" o' e& k7 `8 ^/ d. i
    unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);  ]7 H! j3 P& d; ?! |. V( u9 a
    unsigned int ThreeQuarters    = (unsigned int)((BitsInUnignedInt  * 3) / 4);
6 O2 c, n0 S% t    unsigned int OneEighth = (unsigned int)(BitsInUnignedInt / 8);; O1 l" _7 r* g+ [# ~7 f$ 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