Hash学习(2)-Hash函数
来源:互联网 发布:淘宝卖家需要什么软件 编辑:程序博客网 时间:2024/06/05 02:28
一个好的hash函数一般具有以下两个特点:第一,速度快,第二,能够将散列键均匀的分布在整个表中,保证不会产生聚集。通常,hash函数具有如下形式:
hash-key = calculated-key % tablesize
上一节主要讨论了一下tablesize,为了提高散列键的离散程度,tablesize通常取素数。一般而言,没有绝对好的hash函数,hash函数的好坏很大程度上依赖于输入键的结构,人们讨论的最多的一般都是输入键为普通字符串的情况。这里也以字符串为例讨论如何一步步优化hash函数。
当键是字符串时,一种选择策略是简单的将字符串中每个字符的ASCII码加起来,代码如下:
unsigned int hash(const char *key, unsigned int tableSize){unsigned int hashVal;while(*key != '\0')hashVal += *key++;return (hashVal % tableSize);}上面的hash函数实现简单而且能够很快的算出答案,不过,如果表很大,则函数就不能很好的分配键,例如,设tableSize=10949,并设所有的键至多8个字符长,由于ASCII字符的值最多是127,因此hash函数只能在0~1016之间取值,其中1016为127*8,显然这不是一种均匀的分配。
下面的hash函数对针对上面的缺点进行了改进。
unsigned int hash(const char *key, unsigned int tableSize){return (key[0] + 27*key[1] + 729*key[2]) % tableSize;}这个hash函数假设key至少有3个字符。值27表示英文字母表的字母个数外加一个空格,而729是27的平方。虽然该函数只考察了前三个字符,但是,假如字符出现的概率是随机的,而表的大小还是10949,那么我们就会得到一个合理的均衡分布。可是,英文不是随机的。虽然3个字符有26*26*26=17567种可能的组合,但查验词汇量足够大的联机词典却揭示出:3个字母的不同组合数实际上只有2851种。即使这些组合没有冲突,也不过只有表的28%被真正散列到。因此,虽然容易计算,但是当hash表足够大的时候,这个函数还是不合适。
针对以上缺点,进一步改进:
unsigned int hash(const char *key,unsigned int tableSize){unsigned int hashVal;while(*key != '\0')hashVal = (hashVal << 5) + *key++;return (hashVal % tableSize);}这个hash函数涉及键中的所有字符,并且一般可以分布的很好,它计算了字符串的如下值:
在计算该值时,利用了Horner法则,例如计算 hash=a+32b+32*32c 的另一种方式是借助公式:hash=((c)*32+b)*32+a。Horner法则将其扩展到用于n次多项式。该算法通过将乘法运算转换为位运算保证了hash函数快速的特点。
下面给出实际字符串hash应用中使用的很广的一个hash函数:ELFhash
unsigned long ELfHash(const unsigned char * key){unsigned long h = 0, g;while(*key){h = (h << 4) + *key++;//把h左移4位加上该字符赋给hif(g = h & 0xF0000000)//取h的高四位赋给gh ^= g >> 24;//如果g不为0,让h和g的高八位异或再赋给hh &= ~g;//对g取反并与h相与赋给h}return h;}
- Hash学习(2)-Hash函数
- Hash学习(2)-Hash函数
- Hash函数学习笔记
- 【学习笔记】hash表和hash函数
- Hash 函数、Hash表
- HASH(哈希表)学习
- hash函数
- hash函数
- hash函数
- hash函数
- Hash函数
- Hash函数
- Hash函数
- hash函数
- hash函数
- Hash函数
- hash函数
- Hash函数
- 语记
- 初学Qt 登陆对话框
- 过滤器的实现(清除缓存)
- 网络连接慢,设置ip过程中碰到的问题
- 文件下载
- Hash学习(2)-Hash函数
- oracle性能优化
- Filter(过滤器)简介
- 通过Qt4.2样式表定制程序外观
- Linux驱动子系统之I2C(6)
- 给定目录结构逐级创建相应的文件夹 CreateDirectoryFromPath
- Silverlight中使用配置文件的方法
- 鼠标移到GridView某一行时改变该行的背景色方法二
- svn在linux下的使用(svn命令行)