基本概念

所谓完美哈希函数。就是指没有冲突的哈希函数。即对随意的 key1 != key2 有h(key1) != h(key2)。

设定义域为X,值域为Y, n=|X|,m=|Y|。那么肯定有m>=n,假设对于不同的key1,key2属于X,有h(key1)!=h(key2),那么称h为完美哈希函数,当m=n时,h称为最小完美哈希函数(这个时候就是一一映射了)。



在处理大规模字符串数据时。常常要为每一个字符串分配一个整数ID。这就须要一个字符串的哈希函数。怎么样找到一个完美的字符串hash函数呢?

有一些经常使用的字符串hash函数。

像BKDRHash,APHash。DJBHash。JSHash,RSHash。SDBMHash,PJWHash。ELFHash等等。都是比較经典的。

经常使用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法。

这些函数使用位运算使得每个字符都对最后的函数值产生影响。另外还有以MD5和SHA1为代表的杂凑函数。这些函数差点儿不可能找到碰撞。

经常使用字符串哈希函数有 BKDRHash。APHash。DJBHash,JSHash,RSHash,SDBMHash,PJWHash,ELFHash等等。对于以上几种哈希函数。我对其进行了一个小小的评測。

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效果最差,但得分相似,其算法本质是相似的。

unsigned int SDBMHash(char *str)
{
unsigned int hash = 0; while (*str)
{
// equivalent to: hash = 65599*hash + (*str++);
hash = (*str++) + (hash << 6) + (hash << 16) - hash;
} return (hash & 0x7FFFFFFF);
} // RS Hash Function
unsigned int RSHash(char *str)
{
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0; while (*str)
{
hash = hash * a + (*str++);
a *= b;
} return (hash & 0x7FFFFFFF);
} // JS Hash Function
unsigned int JSHash(char *str)
{
unsigned int hash = 1315423911; while (*str)
{
hash ^= ((hash << 5) + (*str++) + (hash >> 2));
} return (hash & 0x7FFFFFFF);
} // P. J. Weinberger Hash Function
unsigned int PJWHash(char *str)
{
unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);
unsigned int ThreeQuarters = (unsigned int)((BitsInUnignedInt * 3) / 4);
unsigned int OneEighth = (unsigned int)(BitsInUnignedInt / 8);
unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnignedInt - OneEighth);
unsigned int hash = 0;
unsigned int test = 0; while (*str)
{
hash = (hash << OneEighth) + (*str++);
if ((test = hash & HighBits) != 0)
{
hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
}
} return (hash & 0x7FFFFFFF);
} // ELF Hash Function
unsigned int ELFHash(char *str)
{
unsigned int hash = 0;
unsigned int x = 0; while (*str)
{
hash = (hash << 4) + (*str++);
if ((x = hash & 0xF0000000L) != 0)
{
hash ^= (x >> 24);
hash &= ~x;
}
} return (hash & 0x7FFFFFFF);
} // 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);
} // DJB Hash Function
unsigned int DJBHash(char *str)
{
unsigned int hash = 5381; while (*str)
{
hash += (hash << 5) + (*str++);
} return (hash & 0x7FFFFFFF);
} // AP Hash Function
unsigned int APHash(char *str)
{
unsigned int hash = 0;
int i; for (i=0; *str; i++)
{
if ((i & 1) == 0)
{
hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));
}
else
{
hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));
}
} return (hash & 0x7FFFFFFF);
}

编程珠玑中的一个hash函数

//用跟元素个数最接近的质数作为散列表的大小
#define NHASH 29989
#define MULT 31 unsigned in hash(char *p)
{
unsigned int h = 0;
for (; *p; p++)
h = MULT *h + *p;
return h % NHASH;
}

经常使用哈希函数的比較及其C语言实现的更多相关文章

  1. 字符串哈希函数(String Hash Functions)

    哈希函数举例 http://www.cse.yorku.ca/~oz/hash.html Node.js使用的哈希函数 https://www.npmjs.org/package/string-has ...

  2. lintcode:哈希函数

    题目: 哈希函数 在数据结构中,哈希函数是用来将一个字符串(或任何其他类型)转化为小于哈希表大小且大于等于零的整数.一个好的哈希函数可以尽可能少地产生冲突.一种广泛使用的哈希函数算法是使用数值33,假 ...

  3. Eight(bfs+全排列的哈希函数)

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22207   Accepted: 9846   Special Judge ...

  4. 算法初级面试题05——哈希函数/表、生成多个哈希函数、哈希扩容、利用哈希分流找出大文件的重复内容、设计RandomPool结构、布隆过滤器、一致性哈希、并查集、岛问题

    今天主要讨论:哈希函数.哈希表.布隆过滤器.一致性哈希.并查集的介绍和应用. 题目一 认识哈希函数和哈希表 1.输入无限大 2.输出有限的S集合 3.输入什么就输出什么 4.会发生哈希碰撞 5.会均匀 ...

  5. lintcode-->哈希函数

    在数据结构中,哈希函数是用来将一个字符串(或任何其他类型)转化为小于哈希表大小且大于等于零的整数.一个好的哈希函数可以尽可能少地产生冲突.一种广泛使用的哈希函数算法是使用数值33,假设任何字符串都是基 ...

  6. php的哈希函数

    哈希函数: echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n"; 验证函数: boolean  ...

  7. djb2:一个产生简单的随机分布的哈希函数

    目录 LCG算法 示例代码 djb2 示例代码 为什么选择参数33和 33 was chosen because: 5381 was chosen because 哈希选择参考 LCG算法 djb2与 ...

  8. lintcode-128-哈希函数

    128-哈希函数 在数据结构中,哈希函数是用来将一个字符串(或任何其他类型)转化为小于哈希表大小且大于等于零的整数.一个好的哈希函数可以尽可能少地产生冲突.一种广泛使用的哈希函数算法是使用数值33,假 ...

  9. Java集合(八)哈希表及哈希函数的实现方式

    Java集合(八)哈希表及哈希函数的实现方式 一.哈希表 非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的关系,查找的过程为给定值一次和各个关键字进行比较,查找的效率取决于和给定值进行比较的 ...

随机推荐

  1. Linux入门(一)root密码设置和用户切换

    从这学期开始,本人将会亲自开一个Linux 专题学习包括Linux 常用命令,常见问题的一些解决方法,以及Linux系统下C和C++一些学习经验 下面这张图片是首次安装Ubuntu后第一次设置root ...

  2. HDU 4597 Play Game(区间DP(记忆化搜索))

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597 题目大意: 有两行卡片,每个卡片都有各自的权值. 两个人轮流取卡片,每次只能从任一行的左端或右端 ...

  3. CF3A 【Shortest path of the king】

    一句话题意:在8 * 8的棋盘上,输出用最少步数从起点走到终点的方案 数据很小,可以广搜无脑解决 定义数据结构体 struct pos{ int x,y,s; //x.y表示横纵坐标,s表示步数 ]; ...

  4. 【Java】 int与String类型间的相互转化

    public class Test { public static void main(String[] args) { /* * int类型转String类型 */ int n1 = 9; //1. ...

  5. 001 Java 深拷贝、浅拷贝及Cloneable接口

    原本写过,后来在阅读的时候,感觉自己都不是太明白了,删除后参考人家的又重新写了一份. 一:开篇 1.复制一个变量 举例是int类型. 其他其中七种原始数据类型同样适用. 原始类型:boolean,ch ...

  6. Python下opencv使用笔记(图像的平滑与滤波)

    对于图形的平滑与滤波,但从滤波角度来讲,一般主要的目的都是为了实现对图像噪声的消除,增强图像的效果. 对于2D图像可以进行低通或者高通滤波操作 低通滤波(LPF):有利于去噪,模糊图像 高通滤波(HP ...

  7. Bzoj4548 小奇的糖果(链表+树状数组)

    题面 Bzoj 题解 很显然,我们只需要考虑单独取线段上方的情况,对于下方的把坐标取反再做一遍即可(因为我们只关心最终的答案) 建立树状数组维护一个横坐标区间内有多少个点,维护双向链表实现查询一个点左 ...

  8. Python2字符编码问题汇总

    目录 从字符编码说起 unicode与utf-8 当编解码遇上Python2.x unicode 与 str 区别 __str__ __repr__的区别 unicode str utf-8关系 un ...

  9. hdu1242Rescue

     STL容器之优先队列 优先级队列,以前刷题的时候用的比较熟,现在竟然我只能记得它的关键字是priority_queue(太伤了).在一些定义了权重的地方这个数据结构是很有用的. 先回顾队列的定义 ...

  10. 最大子段和问题Java实现

    最大子段和问题 一.问题描述 给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i , j]使得a[i]+…+a[j]和最大. 例如(-2,11,-4,13,-5,2)的最大子段和为 ...