字符串hash处理方式

转载 2013年12月03日 09:36:22




字符串hash处理方式

转载自:http://hi.baidu.com/roxws/item/358954aaacfecd9a151073e9

数字类型做hash表,通常我们会直接把数字直接作为hash表定位的key使用。

字符串,就比较困难。简单的处理方式可能有:

1、取字符串前4个字符当作key

2、md5后取前4个字节当作key,或crc

3、字符串先经过一些算法,算成一个int。比较有代表的是 times 33算法,在效率和冲突率都表现不错。

有了hash key值,就可以把不同字符串均匀分布在hash表内。

而对于实际的字符串比较,apach中采用的分级的方式。会取其前面的4个字符计算该字符串的校验码,所以在实际比较时,会先比较校验码,再用strcasecmp比较两个字符串。而如果我们使用的是md5方式,则可以通过比较md5直接确定字符串是否相同。md5冲突(即不同的字符串md5以后得到相同的md5数值)在目前大部分公司都没有处理。

暴雪的哈希算法 - [转载]暴雪公司有个经典的字符串的hash公式 

先提一个简单的问题,假如有一个庞大的字符串数组,然后给你一个单独的字符串,让你从这个数组中查找是否有这个字符串并找到它,你会怎么做? 

有一个方法最简单,老老实实从头查到尾,一个一个比较,直到找到为止,我想只要学过程序设计的人都能把这样一个程序作出来,但要是有程序员把这样的程序交给用户,我只能用无语来评价,或许它真的能工作,但...也只能如此了。 

最合适的算法自然是使用HashTable(哈希表),先介绍介绍其中的基本知识,所谓Hash,一般是一个整数,通过某种算法,可以把一个字符串"压缩" 成一个整数,这个数称为Hash,当然,无论如何,一个32位整数是无法对应回一个字符串的,但在程序中,两个字符串计算出的Hash值相等的可能非常小,下面看看在MPQ中的Hash算法 

unsigned long HashString(char *lpszFileName, unsigned long dwHashType) 

unsigned char *key = (unsigned char *)lpszFileName; 
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE; 
int ch; 

while(*key != 0) 

ch = toupper(*key ); 

seed1 = cryptTable[(dwHashType < < 8) ch] ^ (seed1 seed2); 
seed2 = ch seed1 seed2 (seed2 < < 5) 3; 

return seed1; 


Blizzard的这个算法是非常高效的,被称为"One-Way Hash",举个例子,字符串"unitneutralacritter.grp"通过这个算法得到的结果是0xA26067F3。 
是不是把第一个算法改进一下,改成逐个比较字符串的Hash值就可以了呢,答案是,远远不够,要想得到最快的算法,就不能进行逐个的比较,通常是构造一个哈希表(Hash Table)来解决问题,哈希表是一个大数组,这个数组的容量根据程序的要求来定义,例如1024,每一个Hash值通过取模运算 (mod)对应到数组中的一个位置,这样,只要比较这个字符串的哈希值对应的位置又没有被占用,就可以得到最后的结果了,想想这是什么速度?是的,是最快的O(1),现在仔细看看这个算法吧 

int GetHashTablePos(char *lpszString, SOMESTRUCTURE *lpTable, int nTableSize) 

int nHash = HashString(lpszString), nHashPos = nHash % nTableSize; 

if (lpTable[nHashPos].bExists && !strcmp(lpTable[nHashPos].pString, lpszString)) 
return nHashPos; 
else 
return -1; //Error value 


看到此,我想大家都在想一个很严重的问题:"假如两个字符串在哈希表中对应的位置相同怎么办?",究竟一个数组容量是有限的,这种可能性很大。解决该问题的方法很多,我首先想到的就是用"链表",感谢大学里学的数据结构教会了这个百试百灵的法宝,我碰到的很多算法都可以转化成链表来解决,只要在哈希表的每个入口挂一个链表,保存所有对应的字符串就OK了。 

事情到此似乎有了完美的结局,假如是把问题独自交给我解决,此时我可能就要开始定义数据结构然后写代码了。然而Blizzard的程序员使用的方法则是更精妙的方法。基本原理就是:他们在哈希表中不是用一个哈希值而是用三个哈希值来校验字符串。 

中国有句古话"再一再二不能再三再四",看来Blizzard也深得此话的精髓,假如说两个不同的字符串经过一个哈希算法得到的入口点一致有可能,但用三个不同的哈希算法算出的入口点都一致,那几乎可以肯定是不可能的事了,这个几率是1:18889465931478580854784,大概是10的 22.3次方分之一,对一个游戏程序来说足够安全了。 

现在再回到数据结构上,Blizzard使用的哈希表没有使用链表,而采用"顺延"的方式来解决问题,看看这个算法: 
int GetHashTablePos(char *lpszString, MPQHASHTABLE *lpTable, int nTableSize) 

const int HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2; 
int nHash = HashString(lpszString, HASH_OFFSET); 
int nHashA = HashString(lpszString, HASH_A); 
int nHashB = HashString(lpszString, HASH_B); 
int nHashStart = nHash % nTableSize, nHashPos = nHashStart; 

while (lpTable[nHashPos].bExists) 

if (lpTable[nHashPos].nHashA == nHashA && lpTable[nHashPos].nHashB == nHashB) 
return nHashPos; 
else 
nHashPos = (nHashPos 1) % nTableSize; 

if (nHashPos == nHashStart) 
break; 


return -1; //Error value 


1. 计算出字符串的三个哈希值(一个用来确定位置,另外两个用来校验) 
2. 察看哈希表中的这个位置 
3. 哈希表中这个位置为空吗?假如为空,则肯定该字符串不存在,返回 
4. 假如存在,则检查其他两个哈希值是否也匹配,假如匹配,则表示找到了该字符串,返回 
5. 移到下一个位置,假如已经越界,则表示没有找到,返回 
6. 看看是不是又回到了原来的位置,假如是,则返回没找到 
7. 回到3 

怎么样,很简单的算法吧,但确实是天才的idea, 其实最优秀的算法往往是简单有效的算法。

求一个字符串的hash值

转载自:http://www.cnblogs.com/jiu0821/p/4554352.html 求一个字符串的hash值: •现在我们希望找到一个hash函数,使得每一个字符串都能够映射到一个...
  • zsc2014030403015
  • zsc2014030403015
  • 2016年04月28日 14:37
  • 2945

经典字符串hash函数介绍及性能比较 + 暴雪公司hash算法

(转自:http://blog.csdn.net/djinglan/article/details/8812934,感谢原作者) 今天根据自己的理解重新整理了一下几个字符串hash函数,使用了模板,使...
  • xu20082100226
  • xu20082100226
  • 2016年09月24日 16:07
  • 2861

经典字符串hash函数介绍及性能比较

各种字符串Hash函数 http://www.cnblogs.com/atlantis13579/archive/2010/02/06/1664792.html http://blog.csdn....
  • djinglan
  • djinglan
  • 2013年04月17日 11:08
  • 22374

程序员必备:字符串哈希函数比较

一个股票交易系统的后台,为了能快速查找各种股票代码的Tick,会计算其哈希值,然后存贮在哈希表里面。一个好的哈希函数应该能实现很好地分布性,减少冲突。这里选取了几种常用的字符串哈希,包括BKDRHas...
  • AlburtHoffman
  • AlburtHoffman
  • 2014年02月23日 22:19
  • 3729

使用哈希表快速查找字符串的一种解决方案

必备知识: 什么是哈希表? 哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一...
  • jzjwonderful
  • jzjwonderful
  • 2016年09月09日 11:26
  • 1902

ELFhash - 优秀的字符串哈希算法

1.字符串哈希: 我们先从字符串哈希说起 在很多的情况下,我们有可能会获得大量的字符串,每个字符串有可能重复也有可能不重复 C不像Python有字典类型的数据结构,我们没有办法吧字符串当做是键值来保存...
  • ltyqljhwcm
  • ltyqljhwcm
  • 2016年10月29日 22:12
  • 3693

字符串HASH 学习总结 && 模板

/*===================================================*\ 从b串中寻找和a串长度相同的子串,返回开始位置 不保证绝对正确,发生冲突...
  • u011026968
  • u011026968
  • 2014年08月09日 21:08
  • 2588

hash取模一致性哈希

取模 最简单的hash算法 targetServer = serverList[hash(key) % serverList.size] 直接用key的hash值(计算key的hash值...
  • ITbasketplayer
  • ITbasketplayer
  • 2014年11月09日 14:30
  • 7801

RollingHash求字符串匹配

字符串匹配与查找和两个字符串共同子串问题的计算时,有时会想到将字符串中字符看整数,计算一个子串的hash值,以字符串匹配为例,模式串P(长度为L),待匹配串S(长度为n): 1)计算P字符串的Hash...
  • Cindy_zhong
  • Cindy_zhong
  • 2013年08月28日 18:38
  • 992

Rolling Hash(Rabin-Karp 算法)匹配字符串与anagram串

该算法常用的场景字符串中查找子串,字符串中查找anagram形式的子串问题。关于字符串查找与匹配字符串可以理解为字符数组。而字符可以被转换为整数,他们具体的值依赖于他们的编码方式(ASCII/Unic...
  • yanghua_kobe
  • yanghua_kobe
  • 2013年05月11日 18:11
  • 8972
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:字符串hash处理方式
举报原因:
原因补充:

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