哈希算法(Hash Algorithm)初探

原创 2007年03月12日 11:39:00
不约而同的,几乎所有的流行的hash map都采用了DJB hash function,俗称“Times33”算法。

Perl、Berkeley DB 、Apache、MFC、STL 等等。

times33的算法也很简单,就是不断的乘33。nHash = nHash*33 + *key++;

我没找到什么理论可以说明这种算法的合理性,据说只是通过测试和实践发现这个算法是比较好的。如果有哪位能够提供这方面的资料,不胜感激。

我把times33和一些其他哈希算法做过比较,times33确实比我找到的其他哈希算法都更快。另外,有人说times33对英文字母效率比较好,处理中文的时候效率就比较低;我对此进行了一些测试,发现times33在处理ascii和中文的时候,性能差异在千分之三以下,我认为这是正常的误差。



《打造最快的Hash表(和Blizzard的对话)》http://blog.csdn.net/zeronecpp/archive/2005/04/11/342756.aspx
这是在别人的blog上看到的一篇文章,讲述blizzard如何改良hash表的。在上述哈希算法里面有一段 “seed2 + (seed2 << 5)” 相当于乘以33,其实可以看作是times33算法的变种。我对blizzard这种实现方法的效率存有怀疑。

上述blizzard的哈希算法的核心如下(我给cryptTable赋了最简单的值,而且把dwHashType设为了1):

inline UINT CMyMap::HashKey(LPCTSTR key) const
{
    int dwHashType = 1;
    unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
    int ch;
    while(*key != 0)
    {
        ch = toupper(*key++);
       
        //seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
        seed1 = ((dwHashType << 8) + ch) ^ (seed1 + seed2);
        seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
    }
    return seed1;
}

我进行了一下测试,发现blizzard的哈希算法,分布不如经典的times33算法。它的分布如下:elements=10000, good=4293 bad2=1786 bad3=528 bad4=109 vbad=22
而经典times33算法的分布是:elements=10000, good=4443 bad2=1775 bad3=501 bad4=107 vbad=15
说明:这是我测试程序的输出,测试的时候,我通过InitHashTable()把bucket个数设为了12007。输出中的elements表示哈希表中一共存放了多少个元素,good表示“只有一个元素”的bucket个数,bad2表示“有两个元素”的bucket个数,bad3表示“有三个元素”的bucket个数,vbad表示“有五个或者五个以上元素”的bucket个数。

经典times33算法如下:
inline UINT CMyMap::HashKey(LPCTSTR key) const
{
    UINT nHash = 0;
    while (*key)
        nHash = (nHash<<5) + nHash + *key++;
    return nHash;
}
从代码可以很明显的看出,blizzard的这个hash算法的计算工作量也要比经典的times33算法大很多。

我的理解是:这是为了让让同一个字符串,可以根据dwHashType 的不同而计算出不同的独立的hash值。为了实现这个目的,blizzard的这个hash算法在性能上已经付出了一些代价。

//
// 以上是对hash算法的比较
/////////////////////////////////////////
// 以下是对hash表整体结构的比较
//

另外,blizzard这个算法本质上还是把数据放在hash bucket里面,也同样是在每个hash bucket里面有一个list队列。
只不过一般的hash表,在找到hash bucket之后,就逐个的直接比较element;而blizzard的这个hash表,则是用“额外的两个hash值的比较”来代替element的直接比较。孰优孰劣要看具体的应用环境。
考虑到计算三次hash值的工作量,我觉得如果设置一个合适的hash bucket count,blizzard的做法可能还要更慢。
上面我做的hash分布测试已经表明,当hash bucket count比elements大20%以上的时候,查找一个element的strcmp调用次数大约是(4443*1+1175*2*1.5+501*3*2+107*4*2.5+15*5*3)/10000=1.2269次,大约是1.2次。(4443个bucket只有一个element,因此一次strcmp就可以确认了。有1175个bucket有两个元素,平均要1.5次strcmp才能找到它。以此类推。)
做1.2次strcmp()和做2次HashKey()相信大家都知道谁比较耗时了。


看来,这个所谓”最快的hash表“似乎有点名不副实呢?还是另有玄机我没看透?
所谓"One-way hash"其实就是不可逆hash,主要是用来加密用的,和速度快不快没什么关系。实际上"One-way hash"为了达到不可逆的目的,通常总是要更慢一些。blizzard是我很喜欢的公司,我也是暴雪的铁杆fans,不过这次似乎有人夸暴雪夸错方向了:)

在google上搜索“hash Algorithm”可以搜到很多有趣的东西。
http://www.partow.net/programming/hashfunctions/ 是一篇很有趣的文章。

hash算法原理详解

一.概念 哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。 哈希的思路很简单,如果所有的键都是整数,那么就可以使用一个简单的无...
  • tanggao1314
  • tanggao1314
  • 2016年05月19日 22:35
  • 57645

每天进步一点点——五分钟理解一致性哈希算法(consistent hashing)

五分钟让你深入了解分布式系统中常用的一致性哈希算法
  • cywosp
  • cywosp
  • 2014年04月11日 00:21
  • 354345

几种经典的hash算法

计算理论中,没有Hash函数的说法,只有单向函数的说法。所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数据。用“人 类”的语言描述单向函数就是:如果某个函数在给定输入的时候,很...
  • jason5186
  • jason5186
  • 2013年06月06日 11:47
  • 32410

Hash算法总结

Hash是什么,它的作用先举个例子。我们每个活在世上的人,为了能够参与各种社会活动,都需要一个用于识别自己的标志。也许你觉得名字或是身份证就足以代表你这个人,但是这种代表性非常脆弱,因为重名的人很多,...
  • asdzheng
  • asdzheng
  • 2017年04月18日 11:07
  • 3867

详解哈希算法、哈希表

哈希算法详解 何为哈希算法哈希算法又称为散列技术(Hash技术),哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。...
  • lyp_558
  • lyp_558
  • 2015年10月29日 21:14
  • 1016

几种经典的hash算法

文章出处:http://hunteagle.javaeye.com 注:最近因为在做和hash有关的题目,感到很纠结。虽然上学期数据结构学过,但是当时觉得hash没什么用,所以没有认真学~后悔啊...
  • xiaoxufox
  • xiaoxufox
  • 2015年12月09日 09:54
  • 751

常见的Hash算法

简介哈希方法学哈希函数和素数位偏移各种形式的哈希常用的哈希函数各版本哈希代码下载简介哈稀函数按照定义可以实现一个伪随机数生成器(PRNG),从这个角度可以得到一个公认的结论:哈希函数之间性能的比较可以...
  • eaglex
  • eaglex
  • 2011年04月08日 22:31
  • 32731

浅析Hash算法

HASH 算法是一种消息摘要算法,不是一种加密算法,但由于其单向运算,具有一定的不可逆性,成为加密算法中的一个构成部分,完整的加密机制不能仅依赖 HASH 算法。 哈希算法是将目标文本转换成具有相同...
  • lucky_greenegg
  • lucky_greenegg
  • 2016年07月13日 15:04
  • 1833

十一、从头到尾解析Hash表算法

十一、从头到尾彻底解析Hash 表算法作者:July、wuliming、pkuoliver  出处:http://blog.csdn.net/v_JULY_v。  说明:本文分为三部分内容,    第...
  • v_JULY_v
  • v_JULY_v
  • 2011年03月17日 15:40
  • 276873

一致性hash算法 - consistent hashing

一致性hash算法(consistenthashing)张亮consistent hashing算法早在1997年就在论文Consistenthashing and random trees中被提出,...
  • sparkliang
  • sparkliang
  • 2010年02月02日 09:19
  • 163991
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:哈希算法(Hash Algorithm)初探
举报原因:
原因补充:

(最多只允许输入30个字)