各种字符串Hash函数比较

原文:http://explorers.iteye.com/blog/698377

  1. 常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法。这些函数使用  
  2.   
  3. 位运算使得每一个字符都对最后的函数值产生影响。另外还有以MD5和SHA1为代表的杂凑函数,  
  4.   
  5. 这些函数几乎不可能找到碰撞。  
  6.   
  7. 常用字符串哈希函数有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash,  
  8.   
  9. PJWHash,ELFHash等等。对于以上几种哈希函数,我对其进行了一个小小的评测。  
  10.   
  11. Hash函数  数据1 数据2 数据3 数据4 数据1得分   数据2得分   数据3得分   数据4得分   平均分  
  12. BKDRHash    2   0   4774    481 96.55   100 90.95   82.05   92.64  
  13. APHash  2   3   4754    493 96.55   88.46   100 51.28   86.28  
  14. DJBHash 2   2   4975    474 96.55   92.31   0   100 83.43  
  15. JSHash  1   4   4761    506 100 84.62   96.83   17.95   81.94  
  16. RSHash  1   0   4861    505 100 100 51.58   20.51   75.96  
  17. SDBMHash    3   2   4849    504 93.1    92.31   57.01   23.08   72.41  
  18. PJWHash 30  26  4878    513 0   0   43.89   0   21.95  
  19. ELFHash 30  26  4878    513 0   0   43.89   0   21.95  
  20.   
  21. 其中数据1100000个字母和数字组成的随机串哈希冲突个数。数据2100000个有意义的英文句  
  22.   
  23. 子哈希冲突个数。数据3为数据1的哈希值与1000003(大素数)求模后存储到线性表中冲突的个数。  
  24.   
  25. 数据4为数据1的哈希值与10000019(更大素数)求模后存储到线性表中冲突的个数。  
  26.   
  27. 经过比较,得出以上平均得分。平均数为平方平均数。可以发现,BKDRHash无论是在实际效果还是  
  28.   
  29. 编码实现中,效果都是最突出的。APHash也是较为优秀的算法。DJBHash,JSHash,RSHash与  
  30.   
  31. SDBMHash各有千秋。PJWHash与ELFHash效果最差,但得分相似,其算法本质是相似的。  
  32.   
  33. 在信息修竞赛中,要本着易于编码调试的原则,个人认为BKDRHash是最适合记忆和使用的。  
  34.   
  35. CmYkRgB123原创,欢迎建议、交流、批评和指正。  
  36.   
  37.    
  38.   
  39. 附:各种哈希函数的C语言程序代码  
  40. unsigned int SDBMHash(char *str)  
  41.   
  42.   
  43. {  
  44.     unsigned int hash = 0;  
  45.    
  46.     while (*str)  
  47.     {  
  48.         // equivalent to: hash = 65599*hash + (*str++);  
  49.         hash = (*str++) + (hash << 6) + (hash << 16) - hash;  
  50.     }  
  51.    
  52.     return (hash & 0x7FFFFFFF);  
  53. }  
  54.    
  55. // RS Hash   
  56. unsigned int RSHash(char *str)  
  57. {  
  58.     unsigned int b = 378551;  
  59.     unsigned int a = 63689;  
  60.     unsigned int hash = 0;  
  61.    
  62.     while (*str)  
  63.     {  
  64.         hash = hash * a + (*str++);  
  65.         a *= b;  
  66.     }  
  67.    
  68.     return (hash & 0x7FFFFFFF);  
  69. }  
  70.    
  71. // JS Hash   
  72. unsigned int JSHash(char *str)  
  73. {  
  74.     unsigned int hash = 1315423911;  
  75.    
  76.     while (*str)  
  77.     {  
  78.         hash ^= ((hash << 5) + (*str++) + (hash >> 2));  
  79.     }  
  80.    
  81.     return (hash & 0x7FFFFFFF);  
  82. }  
  83.    
  84. // P. J. Weinberger Hash   
  85. unsigned int PJWHash(char *str)  
  86. {  
  87.     unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);  
  88.     unsigned int ThreeQuarters  = (unsigned int)((BitsInUnignedInt  * 3) / 4);  
  89.     unsigned int OneEighth = (unsigned int)(BitsInUnignedInt / 8);  
  90.     unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnignedInt   
  91.   
  92.                                                - OneEighth);  
  93.     unsigned int hash   = 0;  
  94.     unsigned int test   = 0;  
  95.    
  96.     while (*str)  
  97.     {  
  98.         hash = (hash << OneEighth) + (*str++);  
  99.         if ((test = hash & HighBits) != 0)  
  100.         {  
  101.             hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));  
  102.         }  
  103.     }  
  104.    
  105.     return (hash & 0x7FFFFFFF);  
  106. }  
  107.    
  108. // ELF Hash   
  109. unsigned int ELFHash(char *str)  
  110. {  
  111.     unsigned int hash = 0;  
  112.     unsigned int x  = 0;  
  113.    
  114.     while (*str)  
  115.     {  
  116.         hash = (hash << 4) + (*str++);  
  117.         if ((x = hash & 0xF0000000L) != 0)  
  118.         {  
  119.             hash ^= (x >> 24);  
  120.             hash &= ~x;  
  121.         }  
  122.     }  
  123.    
  124.     return (hash & 0x7FFFFFFF);  
  125. }  
  126.    
  127. // BKDR Hash   
  128. unsigned int BKDRHash(char *str)  
  129. {  
  130.     unsigned int seed = 131// 31 131 1313 13131 131313 etc..  
  131.     unsigned int hash = 0;  
  132.    
  133.     while (*str)  
  134.     {  
  135.         hash = hash * seed + (*str++);  
  136.     }  
  137.    
  138.     return (hash & 0x7FFFFFFF);  
  139. }  
  140.    
  141. // DJB Hash   
  142. unsigned int DJBHash(char *str)  
  143. {  
  144.     unsigned int hash = 5381;  
  145.    
  146.     while (*str)  
  147.     {  
  148.         hash += (hash << 5) + (*str++);  
  149.     }  
  150.    
  151.     return (hash & 0x7FFFFFFF);  
  152. }  
  153.    
  154. // AP Hash   
  155. unsigned int APHash(char *str)  
  156. {  
  157.     unsigned int hash = 0;  
  158.     int i;  
  159.    
  160.     for (i=0; *str; i++)  
  161.     {  
  162.         if ((i & 1) == 0)  
  163.         {  
  164.             hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));  
  165.         }  
  166.         else  
  167.         {  
  168.             hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));  
  169.         }  
  170.     }  
  171.    
  172.     return (hash & 0x7FFFFFFF);  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值