【Hash】字符串哈希
Hash 的核心思想在于,将输入映射到一个值域较小、可以方便比较的范围,典型的用法就是将资源紧张的设备中的不定长字符串转化为定长整数,以达到节省空间的目的
如:printf("This is a string.") => printf("0x12345678") // 理想哈希算法可将不同的字符串转化为唯一的整数
常用hash算法:
- 00 - RS 哈希函数
unsigned int RSHash(const char* str, unsigned int length) { unsigned int b = 378551; unsigned int a = 63689; unsigned int hash = 0; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash = hash * a + (*str); a = a * b; } return hash; }
- 01 - JS 哈希函数
unsigned int JSHash(const char* str, unsigned int length) { unsigned int hash = 1315423911; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash ^= ((hash << 5) + (*str) + (hash >> 2)); } return hash; }
- 02 - PJW 哈希函数
unsigned int PJWHash(const char* str, unsigned int length) { const unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8); const unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt * 3) / 4); const unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8); const unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth); unsigned int hash = 0; unsigned int test = 0; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash = (hash << OneEighth) + (*str); if ((test = hash & HighBits) != 0) { hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits)); } } return hash; }
- 03 - ELF哈希函数
unsigned int ELFHash(const char* str, unsigned int length) { unsigned int hash = 0; unsigned int x = 0; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash = (hash << 4) + (*str); if ((x = hash & 0xF0000000L) != 0) { hash ^= (x >> 24); } hash &= ~x; } return hash; }
- 04 - BKDR 哈希函数
unsigned int BKDRHash(const char* str, unsigned int length) { unsigned int seed = 131; /* 31 131 1313 13131 131313 etc.. */ unsigned int hash = 0; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash = (hash * seed) + (*str); } return hash; }
- 05 - SDBM哈希函数
unsigned int SDBMHash(const char* str, unsigned int length) { unsigned int hash = 0; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash = (*str) + (hash << 6) + (hash << 16) - hash; } return hash; }
- 06 - DJB哈希函数
unsigned int DJBHash(const char* str, unsigned int length) { unsigned int hash = 5381; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash = ((hash << 5) + hash) + (*str); } return hash; }
- 07 - DEK哈希函数
unsigned int DEKHash(const char* str, unsigned int length) { unsigned int hash = len; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash = ((hash << 5) ^ (hash >> 27)) ^ (*str); } return hash; }
- 08 - AP 哈希函数
unsigned int APHash(const char* str, unsigned int length) { unsigned int hash = 0xAAAAAAAA; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (*str) * (hash >> 3)) : (~((hash << 11) + ((*str) ^ (hash >> 5)))); } return hash; }
各hash算法冲突率测评
Hash函数 | 数据1 | 数据2 | 数据3 | 数据4 | 数据1得分 | 数据2得分 | 数据3得分 | 数据4得分 | 平均分 |
BKDRHash | 2 | 0 | 4774 | 481 | 96.55 | 100 | 90.95 | 82.05 | 92.64 |
APHash | 2 | 3 | 4754 | 493 | 96.55 | 88.46 | 100 | 51.28 | 86.28 |
DJBHash | 2 | 2 | 4975 | 474 | 96.55 | 92.31 | 0 | 100 | 83.43 |
JSHash | 1 | 4 | 4761 | 506 | 100 | 84.62 | 96.83 | 17.95 | 81.94 |
RSHash | 1 | 0 | 4861 | 505 | 100 | 100 | 51.58 | 20.51 | 75.96 |
SDBMHash | 3 | 2 | 4849 | 504 | 93.1 | 92.31 | 57.01 | 23.08 | 72.41 |
PJWHash | 30 | 26 | 4878 | 513 | 0 | 0 | 43.89 | 0 | 21.95 |
ELFHash | 30 | 26 | 4878 | 513 | 0 | 0 | 43.89 | 0 | 21.95 |
数据1:为100000个字母和数字组成的随机串哈希冲突个数
数据2:为100000个有意义的英文句子哈希冲突个数
数据3:为数据1的哈希值与 1000003(大素数)求模后存储到线性表中冲突的个数
数据4:为数据1的哈希值与10000019(更大素数)求模后存储到线性表中冲突的个数。
经过比较,得出以上平均得分。平均数为平方平均数。可以发现,BKDRHash无论是在实际效果还是编码实现中,效果都是最突出的。APHash也是较为优秀的算法。DJBHash,JSHash,RSHash与SDBMHash各有千秋。
PJWHash与ELFHash效果最差,但得分相似,其算法本质是相似的。
参考:
http://www.partow.net/programming/hashfunctions/
https://www.cnblogs.com/uvsjoh/archive/2012/03/27/2420120.html
再牛逼的梦想也架不住傻逼似的坚持
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2020-08-03 【C++】类大小