Google的CityHash算法
在学数据结构的时候,大家一定学过散列表,但很多人不知道算列表有什么用,最后只知道做题,这也许就是教育的悲哀吧。
我开始也不知道,但是有一天,我学java的时候,用到了HashTable和HashSet的时候,就想到了散列表,网上查资料才发现散列表的巨大作用。
言归正传,今天我们来讨论一下字符串哈希算法。常用的简单又高效字符串哈希算有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash,PJWHash,ELFHash等。这些算法都是实现比较简单的,对于小数据量一般都可以满足要求,具体实现和性能,请参看网上的介绍。根据这篇文章的介绍,BKDRHash的效果最好,实现也非常的简单,一般的应用可以采用该哈希算法,这里特别给出这个算法的实现吧。
// 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);
}
如果你看过java中String的hashCode方法的话,你会发现,其算法与BKDRHash算法非常像,可以认为就是一种BKDRHash算法。
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
但是对于一些复杂的应用,或者如果数据量非常大的话,应用这些hash函数就会产生很多碰撞,碰撞的解决办法有多种,比如二次探查或拉链,但这都将影响效率。所以就需要用到复杂一些的哈希函数。有的时候为了安全的考虑,也会用到一些哈希函数,如MD5、SHA1,但这不是我们今天讨论的重点。这些算法复杂度一般会较高,如果仅仅是为减少冲突的话,用MD5和SHA1,或者类似的方法的意义就不是很大。
为了满足大数量的需求,减少碰撞,我们一般需要给出一个64位的哈希,当然前面提到的方法也可以直接用于64位,或者简单改造一下就好。Google在今年的四月份公布了一个叫做CityHash的方法,能比较快的生成一个64位的字符串签名,效率在64位cpu上得到了特殊优化,在工业级应用中可以使用该哈希算法,代码公布在google code上。具体的介绍,可以参看墙内,墙外。
怎么说呢?谷歌在为计算机技术发展做出了很多重要的贡献,谷歌公开发布的论文,开源的代码都广泛被业界所认可,我们在有意或无意的用着google的很多东西。
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名小橋流水(包含链接)。如您有任何疑问或者授权方面的协商,请给我发邮件。