经典字符串Hash函数

       工作中经常需要用大hash这个强有力的工具,hash表最核心的部分则在于怎么设计一个好的hash函数,以使数据更均匀地分布在若干个桶上。下面来介绍一下我现在用到的一个hash函数,我们来看代码:
unsigned chostcachehash::get_host_key(const string& host)
{
 int result = 1;
 unsigned i = 0;
  for (i = 0; i < host.size(); i++)
  result = 31 * result + host[i];
 
 return abs(result);
}
inline unsigned getkey(unsigned key)
 {
  return (key % m_capacity);
 }
m_capacity为hash桶的个数
对于一个字符串,我们首先调用get_host_key()来得到一个key,然后再用这个key调用getkey来得到他在hash桶里的位置。这个是我们在工作一直使用的hash函数,效果也还可以。今天忽然心血来潮,在网上搜了一下看还有没有更好的hash函数,被我发现了这篇文章,于是转过来看看。
php中出现的字符串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;
}
openssl中出现的字符串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; i        %有点看不懂
ret^=(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 == "{post.abstract}"))
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);

mysql中出现的字符串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);
}
 
#endif 


 

从上表可以看出,这些经典软件虽然构造字符串Hash函数的方法不同,但是它们的效率都是不错的,相互之间差距很小,读者可以参考实际情况从其中借鉴使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值