若干经典的字符串哈希函数
来源:互联网 发布:知乎青藏高原形成过程 编辑:程序博客网 时间:2024/05/17 02:20
若干经典的字符串哈希函数
转自:http://www.cnitblog.com/schkui/archive/2007/07/02/29320.html
// RS Hash Function unsigned int RSHash( char * str)
{
unsigned int b = 378551 ;
unsigned int a = 63689 ;
unsigned int hash = 0 ;
while ( * str)
{
hash = hash * a + ( * str ++ );
a *= b;
}
return (hash & 0x7FFFFFFF );
}
// JS Hash Function
unsigned int JSHash( char * str)
{
unsigned int hash = 1315423911 ;
while ( * str)
{
hash ^= ((hash << 5 ) + ( * str ++ ) + (hash >> 2 ));
}
return (hash & 0x7FFFFFFF );
}
// P. J. Weinberger Hash Function
unsigned int PJWHash( char * str)
{
unsigned int BitsInUnignedInt = (unsigned int )( sizeof (unsigned int ) *
8 );
unsigned int ThreeQuarters = (unsigned int )((BitsInUnignedInt * 3 )
/ 4 );
unsigned int OneEighth = (unsigned int )(BitsInUnignedInt / 8 );
unsigned int HighBits = (unsigned int )( 0xFFFFFFFF ) << (BitsInU
nignedInt - 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 Function
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 Function
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 );
}
// SDBM Hash Function
unsigned int SDBMHash( char * str)
{
unsigned int hash = 0 ;
while ( * str)
{
hash = ( * str ++ ) + (hash << 6 ) + (hash << 16 ) - hash;
}
return (hash & 0x7FFFFFFF );
}
// DJB Hash Function
unsigned int DJBHash( char * str)
{
unsigned int hash = 5381 ;
while ( * str)
{
hash += (hash << 5 ) + ( * str ++ );
}
return (hash & 0x7FFFFFFF );
}
// AP Hash Function
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 );
}
比较经典的字符串hash就这些了吧,"ELF Hash Function" <-这个比较常用.
字符串hash算法比较
1概述链表查找的时间效率为O(N),二分法为log2N,B+ Tree为log2N,但Hash链表查找的时间效率为O(1)。设 计高效算法往往需要使用Hash链表,常数级的查找速度是任何别的算法无法比拟的,Hash链表的构造和冲突的不同实现方法对效率当然有一定的影响,然 而Hash函数是Hash链表最核心的部分,本文尝试分析一些经典软件中使用到的字符串Hash函数在执行效率、离散性、空间利用率等方面的性能问题。 2经典字符串Hash函数介绍作者阅读过大量经典软件原代码,下面分别介绍几个经典软件中出现的字符串Hash函数。2.1PHP中出现的字符串Hash函数static unsigned long hashpjw(char *arKey, unsigned int nKeyLength){unsigned long h = 0, g;char *arEnd=arKey+nKeyLength;
while (arKey < arEnd) {h = (h << 4) + *arKey++;if ((g = (h & 0xF0000000))) {h = h ^ (g >> 24);h = h ^ g;}}return h;}2.2OpenSSL中出现的字符串Hash函数unsigned long lh_strhash(char *str){int i,l;unsigned long ret=0;unsigned short *s;
if (str == NULL) return(0);l=(strlen(str)+1)/2;s=(unsigned short *)str;for (i=0; iret^=(s[i]<<(i&0x0f));return(ret);} */
/* The following hash seems to work very well on normal text strings* no collisions on /usr/dict/words and it distributes on %2^n quite* well, not as good as MD5, but still good.*/unsigned long lh_strhash(const char *c){unsigned long ret=0;long n;unsigned long v;int r;
if ((c == NULL) || (*c == '/0'))return(ret);/*unsigned char b[16];MD5(c,strlen(c),b);return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24));*/
n=0x100;while (*c){v=n|(*c);n+=0x100;r= (int)((v>>2)^v)&0x0f;ret=(ret(32-r));ret&=0xFFFFFFFFL;ret^=v*v;c++;}return((ret>>16)^ret);}在下面的测量过程中我们分别将上面的两个函数标记为OpenSSL_Hash1和OpenSSL_Hash2,至于上面的实现中使用MD5算法的实现函数我们不作测试。2.3MySql中出现的字符串Hash函数#ifndef NEW_HASH_FUNCTION
/* Calc hashvalue for a key */
static uint calc_hashnr(const byte *key,uint length){register uint nr=1, nr2=4;while (length--){nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8);nr2+=3;}return((uint) nr);}
/* Calc hashvalue for a key, case indepenently */
static uint calc_hashnr_caseup(const byte *key,uint length){register uint nr=1, nr2=4;while (length--){nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8);nr2+=3;}return((uint) nr);}
#else
/** Fowler/Noll/Vo hash** The basis of the hash algorithm was taken from an idea sent by email to the* IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and* Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com)* later improved on their algorithm.** The magic is in the interesting relationship between the special prime* 16777619 (2^24 + 403) and 2^32 and 2^8.** This hash produces the fewest collisions of any function that we've seen so* far, and works well on both numbers and strings.*/
uint calc_hashnr(const byte *key, uint len){const byte *end=key+len;uint hash;for (hash = 0; key < end; key++){hash *= 16777619;hash ^= (uint) *(uchar*) key;}return (hash);}
uint calc_hashnr_caseup(const byte *key, uint len){const byte *end=key+len;uint hash;for (hash = 0; key < end; key++){hash *= 16777619;hash ^= (uint) (uchar) toupper(*key);}return (hash);}
#endifMysql中对字符串Hash函数还区分了大小写,我们的测试中使用不区分大小写的字符串Hash函数,另外我们将上面的两个函数分别记为MYSQL_Hash1和MYSQL_Hash2。2.4另一个经验字符串Hash函数unsigned int hash(char *str){register unsigned int h;register unsigned char *p;
for(h=0, p = (unsigned char *)str; *p ; p++)h = 31 * h + *p;
return h;}3测试及结果3.1测试说明从上面给出的经典字符串Hash函数中可以看出,有的涉及到字符串大小敏感问题,我们的测试中只考虑字符串大小写敏感的函数,另外在上面的函数中有的函数 需要长度参数,有的不需要长度参数,这对函数本身的效率有一定的影响,我们的测试中将对函数稍微作一点修改,全部使用长度参数,并将函数内部出现的计算长 度代码删除。我们用来作测试用的Hash链表采用经典的拉链法解决冲突,另外我们采用静态分配桶(Hash链表长度)的方法来构造Hash链表,这主要是为了简化我们的实现,并不影响我们的测试结果。测试文本采用单词表,测试过程中从一个输入文件中读取全部不重复单词构造一个Hash表,测试内容分别是函数总调用次数、函数总调用时间、最大拉链长度、 平均拉链长度、桶利用率(使用过的桶所占的比率),其中函数总调用次数是指Hash函数被调用的总次数,为了测试出函数执行时间,该值在测试过程中作了一 定的放大,函数总调用时间是指Hash函数总的执行时间,最大拉链长度是指使用拉链法构造链表过程中出现的最大拉链长度,平均拉链长度指拉链的平均长度。测试过程中使用的机器配置如下:PIII600笔记本,128M内存,windows 2000 server操作系统。3.2测试结果以下分别是对两个不同文本文件中的全部不重复单词构造Hash链表的测试结果,测试结果中函数调用次数放大了100倍,相应的函数调用时间也放大了100倍。从上表可以看出,这些经典软件虽然构造字符串Hash函数的方法不同,但是它们的效率都是不错的,相互之间差距很小,读者可以参考实际情况从其中借鉴使用。
while (arKey < arEnd) {h = (h << 4) + *arKey++;if ((g = (h & 0xF0000000))) {h = h ^ (g >> 24);h = h ^ g;}}return h;}2.2OpenSSL中出现的字符串Hash函数unsigned long lh_strhash(char *str){int i,l;unsigned long ret=0;unsigned short *s;
if (str == NULL) return(0);l=(strlen(str)+1)/2;s=(unsigned short *)str;for (i=0; iret^=(s[i]<<(i&0x0f));return(ret);} */
/* The following hash seems to work very well on normal text strings* no collisions on /usr/dict/words and it distributes on %2^n quite* well, not as good as MD5, but still good.*/unsigned long lh_strhash(const char *c){unsigned long ret=0;long n;unsigned long v;int r;
if ((c == NULL) || (*c == '/0'))return(ret);/*unsigned char b[16];MD5(c,strlen(c),b);return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24));*/
n=0x100;while (*c){v=n|(*c);n+=0x100;r= (int)((v>>2)^v)&0x0f;ret=(ret(32-r));ret&=0xFFFFFFFFL;ret^=v*v;c++;}return((ret>>16)^ret);}在下面的测量过程中我们分别将上面的两个函数标记为OpenSSL_Hash1和OpenSSL_Hash2,至于上面的实现中使用MD5算法的实现函数我们不作测试。2.3MySql中出现的字符串Hash函数#ifndef NEW_HASH_FUNCTION
/* Calc hashvalue for a key */
static uint calc_hashnr(const byte *key,uint length){register uint nr=1, nr2=4;while (length--){nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8);nr2+=3;}return((uint) nr);}
/* Calc hashvalue for a key, case indepenently */
static uint calc_hashnr_caseup(const byte *key,uint length){register uint nr=1, nr2=4;while (length--){nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8);nr2+=3;}return((uint) nr);}
#else
/** Fowler/Noll/Vo hash** The basis of the hash algorithm was taken from an idea sent by email to the* IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and* Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com)* later improved on their algorithm.** The magic is in the interesting relationship between the special prime* 16777619 (2^24 + 403) and 2^32 and 2^8.** This hash produces the fewest collisions of any function that we've seen so* far, and works well on both numbers and strings.*/
uint calc_hashnr(const byte *key, uint len){const byte *end=key+len;uint hash;for (hash = 0; key < end; key++){hash *= 16777619;hash ^= (uint) *(uchar*) key;}return (hash);}
uint calc_hashnr_caseup(const byte *key, uint len){const byte *end=key+len;uint hash;for (hash = 0; key < end; key++){hash *= 16777619;hash ^= (uint) (uchar) toupper(*key);}return (hash);}
#endifMysql中对字符串Hash函数还区分了大小写,我们的测试中使用不区分大小写的字符串Hash函数,另外我们将上面的两个函数分别记为MYSQL_Hash1和MYSQL_Hash2。2.4另一个经验字符串Hash函数unsigned int hash(char *str){register unsigned int h;register unsigned char *p;
for(h=0, p = (unsigned char *)str; *p ; p++)h = 31 * h + *p;
return h;}3测试及结果3.1测试说明从上面给出的经典字符串Hash函数中可以看出,有的涉及到字符串大小敏感问题,我们的测试中只考虑字符串大小写敏感的函数,另外在上面的函数中有的函数 需要长度参数,有的不需要长度参数,这对函数本身的效率有一定的影响,我们的测试中将对函数稍微作一点修改,全部使用长度参数,并将函数内部出现的计算长 度代码删除。我们用来作测试用的Hash链表采用经典的拉链法解决冲突,另外我们采用静态分配桶(Hash链表长度)的方法来构造Hash链表,这主要是为了简化我们的实现,并不影响我们的测试结果。测试文本采用单词表,测试过程中从一个输入文件中读取全部不重复单词构造一个Hash表,测试内容分别是函数总调用次数、函数总调用时间、最大拉链长度、 平均拉链长度、桶利用率(使用过的桶所占的比率),其中函数总调用次数是指Hash函数被调用的总次数,为了测试出函数执行时间,该值在测试过程中作了一 定的放大,函数总调用时间是指Hash函数总的执行时间,最大拉链长度是指使用拉链法构造链表过程中出现的最大拉链长度,平均拉链长度指拉链的平均长度。测试过程中使用的机器配置如下:PIII600笔记本,128M内存,windows 2000 server操作系统。3.2测试结果以下分别是对两个不同文本文件中的全部不重复单词构造Hash链表的测试结果,测试结果中函数调用次数放大了100倍,相应的函数调用时间也放大了100倍。从上表可以看出,这些经典软件虽然构造字符串Hash函数的方法不同,但是它们的效率都是不错的,相互之间差距很小,读者可以参考实际情况从其中借鉴使用。
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数
- 若干经典的字符串哈希函数(转)
- 若干经典哈希算法
- 字符串输入函数的若干不同
- 若干字符串后缀函数
- 经典的字符串hash函数。
- 关于字符串的若干小结
- 世上最经典的若干句话
- 专业术语简称
- JS去除html标签
- WPF中的Resource:DynamicResource与StaticResource的区别
- C#委托和事件
- 上午的工作进度
- 若干经典的字符串哈希函数
- MFC OnFileNew OnFileOpen过程分析代码
- Cortex系列处理器
- 浏览器的加载与页面性能优化
- Android HAL实例解析
- oracle中建立job定期运行存储过程总结
- C#日期函數的使用技巧
- 算法的时间复杂度(计算实例)
- try except语句 和 try finally语句 用法以及区别