最近在作负荷分担的优化,将数据流均匀分到八条流中,学习点哈希算法算法
什么是哈希表?
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它经过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫作散列函数,存放记录的数组叫作散列表。说白了哈希表的原理其实就是经过空间换取时间的作法。。
哈希表的作法其实很简单,就是把Key经过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,而后就将该数字对数组长度进行取余,取余结果就看成数组的下标,将value存储在以该数字为下标的数组空间里。
而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就能够充分利用到数组的定位性能进行数据定位。。数组
哈希函数的构造方法: 数据结构
若对于关键字集合中的任一个关键字,哈希函数映像到地址集合中任何一个地址的几率是相等的,则称此类哈希函数为均匀的哈希函数。换句话说,就是使关键字通过哈希函数获得一个“随机的地址“,以便使一组关键字的哈希地址均匀分布在整个地址区间中,从而减小冲突。
(1)直接定址法
取关键字或关键字的某个线性函数值为哈希地址。即: H(key)=key或H(key)=a*key+b; 其中a和b为常数(这种哈希函数叫作自身函数)。
因为直接定址所得地址集合和关键字集合的大小相同。所以,对于不一样的关键字不会发生冲突。但实际中使用这种哈希函数的状况不多。
(2)数字分析法
假设关键字是以r为基的数(如:以10为基的十进制数),而且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。
(3)平方取中法
取关键字平方后的中间几位为哈希地址。
(4)斐波那契(Fibonacci)散列法
平方散列法的缺点是显而易见的,因此咱们能不能找出一个理想的乘数,而不是拿value自己看成乘数呢?答案是确定的。
1)对于16位整数而言,这个乘数是40503
2)对于32位整数而言,这个乘数是2654435769
3)对于64位整数而言,这个乘数是11400714819323198485
这几个“理想乘数”是如何得出来的呢?这跟一个法则有关,叫黄金分割法则,而描述黄金分割法则的最经典表达式无疑就是著名的斐波那契数列,即如此形式的序列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,…。另外,斐波那契数列的值和太阳系八大行星的轨道半径的比例出奇吻合。
对咱们常见的32位整数而言,公式: index = (value * 2654435769) >> 28
(5)折叠法
将关键字分割成位数相同的几部分(最后一部分的位数能够不一样),而后取这几部分的叠加和(舍去进位)做为哈希地址,这方法称为折叠法。
(6)除留余数法(==最经常使用的方法)
取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即H(key)=key MOD p,(p<=m),这是一种最简单,也是最经常使用的构造哈希函数的方法。它不只能够对关键字直接取模(MOD),也可在折叠、平方取中等运算以后取模。
(7)随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key)=random(key),其中random为随机函数。一般,当关键字长度不等时采用此法构造哈希函数较切当。
总结:
实际工做中需视不一样状况采用不一样的哈希函数,一般,考虑的因素有:
(1)计算哈希函数所需时间(包括硬件指令的因素);
(2)关键字的长度;
(3)哈希表的大小;
(4)关键字的分布状况;
(5)记录的查找频率。dom
处理冲突的方法(冲突只能减小,不能避免):
(1)开放定址法
(2)再哈希法
(3)链地址法
(4)创建一个公共溢出区
哈希表的查找及其分析:
在哈希表上进行查找的过程和哈希造表的过程基本一致。给定的K值,根据造表时设定的哈希函数求得哈希地址,若表中此位置上没有记录,则查找不成功;不然必将关键字,若和给定的值相等,则查找成功;不然根据造表时设定的处理冲突的方法找”下一地址“,直至哈希表中的某个位置为”空“或者表中所填记录的关键字等于给定值时为止。
哈希表的装填因子定义为:
α=(表中填入的记录数)/(哈希表的长度)函数