`
zhaohaolin
  • 浏览: 1011314 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

哈希算法(Hash Algorithm)初探[转载]

阅读更多

不约而同的,几乎所有的流行的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

    哈希算法 Hash 哈希算法 Hash 是一种常用的数据加密技术,用于将任意长度的数据转换为固定长度的哈希值。哈希算法 Hash 的设计目的是为了实现数据的加密和身份验证。下面我们将对哈希算法 Hash 进行详细的介绍和...

    python 密码学示例——理解哈希(Hash)算法

    例如,MD5(Message-Digest Algorithm 5)是一种经典的哈希算法,它能对任意大小的输入生成16字节的摘要,但由于其历史较久和摘要长度较短,现在已不再适用于安全性要求极高的场合。 二、MD5哈希算法实例 在Python...

    Matlab实现感知哈希算法

    **感知哈希算法详解与Matlab实现** 感知哈希(Perceptual Hashing,简称pHash)是一种图像识别技术,用于判断两张图片是否相似。它通过模拟人类视觉系统的感知特性,将图片转换成一个简短的哈希值,进而进行比较。...

    暴雪哈希算法全部源码

    其中,一个被广泛讨论且具有较高学习价值的是暴雪哈希算法(Blizzard Hash Algorithm)。该算法主要应用于处理字符串哈希,特别是在游戏资源管理方面,如文件命名、资源索引等场景中表现出了较高的效率和良好的性能...

    针对8位单片机的哈希算法实现

    SHA1(Secure Hash Algorithm 1)是由美国国家安全局(NSA)设计的,它产生一个160位(20字节)的哈希值,通常表示为40个十六进制数字。SHA1算法基于消息摘要,通过对输入数据进行一系列的数学运算,生成一个不可逆...

    基于python与哈希算法实现图像去重

    哈希(Hash)算法是一种将任意长度的输入(也叫做预映射)通过一个算法,变换成固定长度的输出,这个输出就是哈希值。哈希函数通常设计为单向的,即给定输入容易得到输出,但给定输出很难找到原始输入。在图像去重...

    几个比较著名的哈希算法

    4. SHA-3(Secure Hash Algorithm 3):2015年发布的SHA-3标准,基于Keccak算法,提供了更高的安全性,旨在抵御未来可能出现的攻击方法。SHA-3的变种包括SHA3-224、SHA3-256、SHA3-384和SHA3-512。 哈希算法在软件...

    常用哈希算法代码实现

    在本压缩包中,你可能会找到多种常见的哈希算法的代码实现,如MD5(Message-Digest Algorithm 5)、SHA-1(Secure Hash Algorithm 1)、SHA-256以及SHA-3等。这些算法都具有将任意长度的信息映射为固定长度输出的...

    SHA256、MD5哈希算法实现

    哈希算法,也被称为散列函数,是一种在信息安全领域中广泛应用的技术。它们的主要作用是将任意长度的输入(也称为预映射或消息)转换为固定长度的输出,这个输出通常是一个二进制数字串,被称为哈希值。在本文中,...

    相似图搜索原理-感知哈希算法

    感知哈希算法(Perceptual Hash algorithm)是实现相似图搜索的一种有效方法。它的设计灵感来源于人类视觉系统对图像的感知,即在忽略细节变化的情况下,人眼对图像的主要特征和结构有稳定的识别能力。感知哈希算法...

    C语言下很实用的哈希算法

    哈希算法,也称为散列算法,是一种在计算机科学中广泛使用的数据结构和算法,用于高效地存储和检索数据。...通过阅读`userguide.pdf`和使用`uthash-1.9`库,开发者可以更好地理解和利用哈希算法在实际项目中的潜力。

    blizzard_hash.rar_Blizzard hash_blizzard_哈希算法_暴雪 哈希 算法_暴雪hash

    暴雪哈希(Blizzard Hash)算法是一种由暴雪娱乐公司设计的独特哈希函数,它在计算机科学领域,特别是信息安全和数据处理中占有重要地位。这个算法因其高效性和优秀的抗冲突性能而备受赞誉。哈希算法是将任意长度的...

    哈希算法(Hash Algorithm)是一种将任意长度的二进制数据映射为较短的、固定长度的二进制值的函数.txt

    哈希算法的特点

    ssl证书生成工具解决弱哈希算法签名的SSL证书(CVE-2004-2761)

    弱哈希算法签名的SSL证书(CVE-2004-2761)。 远程服务使用SSL证书链,该证书链已使用加密弱哈希算法(例如MD2、MD4、MD5或SHA1)签名。这些签名算法很容易受到碰撞攻击。攻击者可以利用这一点生成另一个具有相同数字...

    哈希算法详细介绍pdf

    尽管哈希算法有很多种,如MD5、SHA-1等,但SHA-1由于其良好的安全性和可靠性,成为了非常重要的哈希算法之一。 数字签名是电子商务活动中不可或缺的技术,它允许用户通过使用密码学原理来验证信息的来源和完整性。...

    delphi国产哈希算法SM3源码

    delphi下面开发的国产哈希算法SM3可以直接调用接口 里面的代码注释写的很明白 我自己做项目测试了可以使用 没得问题

    论文研究-分布式存储系统的哈希算法研究.pdf

    针对分布式存储系统中如何实现数据在物理存储上的均匀分布和高效定位的问题,对多种哈希算法展开研究,提出了衡量分布式存储系统哈希算法优劣的标准;从散列分布性、哈希冲突和计算效率等多个维度对这些哈希算法进行...

    分布式存储系统的哈希算法研究.pdf

    哈希算法的基本原理是将输入数据(通常是字符串或其他数据类型)通过一种算法转换成固定长度的哈希值(也称为哈希码或者散列值)。由于哈希值的长度是固定的,而输入数据是无限的,所以理论上存在不同的数据产生相同...

    获取哈希及获取哈希算法标识demo-java

    常见的哈希算法有MD5(Message-Digest Algorithm 5)、SHA-1(Secure Hash Algorithm 1)、SHA-256等。例如,要使用MD5算法,可以这样初始化: ```java MessageDigest md = MessageDigest.getInstance("MD5"); `...

Global site tag (gtag.js) - Google Analytics