常见hash算法
hash算法的意义在于提供了一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系,(每一个真实值只能有一个键值,但是一个键值可以对应多个真实值),这样可以快速在数组等条件中里面存取数据.
在网上看了不少HASH资料,所以对HASH的相关资料进行总结和收集。
//HashTable.h template class HashTable{ public : HashTable( int count ) ; void put( T* t ,int key ) ; T* get( int key ) ; private : T** tArray ; }
//HashTable.cpp template HashTable::HashTable( int count ){ tArray = new T*[count] ;} template void HashTable::put( T* t , int key ){ this->tArray[ key ] = t ;}template T* HashTable::get( int key ) { return this->tArray[ key ] ;}
这样,我们只要知道key值,就可以快速存取T类型的数据,而不用像在链表等数据结构中查找一样, 要找来找去的. 至于key值,一般都是用某种算法(所谓的Hash算法)算出来的.例如:字符串的Hash算法, char* value = "hello"; int key = (((((((27* (int)'h'+27)* (int)'e') + 27) * (int)'l') + 27) * (int)'l' +27) * 27 ) + (int)'o' ; Hash函数处理流程Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意内容的输入转换成相同长度输出的加密方式.
我来做一个比喻吧。
我们有很多的小猪,每个的体重都不一样,假设体重分布比较平均(我们考虑到公斤级别),我们按照体重来分,划分成100个小猪圈。
然后把每个小猪,按照体重赶进各自的猪圈里,记录档案。
好了,如果我们要找某个小猪怎么办呢?我们需要每个猪圈,每个小猪的比对吗?
当然不需要了。
我们先看看要找的这个小猪的体重,然后就找到了对应的猪圈了。
在这个猪圈里的小猪的数量就相对很少了。
我们在这个猪圈里就可以相对快的找到我们要找到的那个小猪了。
对应于hash算法。
就是按照hashcode分配不同的猪圈,将hashcode相同的猪放到一个猪圈里。
查找的时候,先找到hashcode对应的猪圈,然后在逐个比较里面的小猪。
所以问题的关键就是建造多少个猪圈比较合适。
如果每个小猪的体重全部不同(考虑到毫克级别),每个都建一个猪圈,那么我们可以最快速度的找到这头猪。缺点就是,建造那么多猪圈的费用有点太高了。
如果我们按照10公斤级别进行划分,那么建造的猪圈只有几个吧,那么每个圈里的小猪就很多了。我们虽然可以很快的找到猪圈,但从这个猪圈里逐个确定那头小猪也是很累的。
所以,好的hashcode,可以根据实际情况,根据具体的需求,在时间成本(更多的猪圈,更快的速度)和空间本(更少的猪圈,更低的空间需求)之间平衡。
Hash算法有很多很多种类。具体的可以参考之前我写的Hash算法的一些分析。本处给大家提供一个集合了很多使用的Hash算法的类,应该可以满足不少人的需要的:
Java代码
常用的字符串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效果最差,但得分相似,其算法本质是相似的。
#define M 249997
#define M1 1000001
#define M2 0xF0000000 // RS Hash Function
unsigned int RSHash(char*str)
{
unsigned int b= ;
unsigned int a= ;
unsigned int hash= ; while(*str)
{
hash=hash*a+(*str++);
a*=b ;
} return(hash % M);
} // JS Hash Function
unsigned int JSHash(char*str)
{
unsigned int hash= ; while(*str)
{
hash^=((hash<<)+(*str++)+(hash>>));
} return(hash % M);
} // P. J. Weinberger Hash Function
unsigned int PJWHash(char*str)
{
unsigned int BitsInUnignedInt=(unsigned int)(sizeof(unsigned int)*);
unsigned int ThreeQuarters=(unsigned int)((BitsInUnignedInt*)/);
unsigned int OneEighth=(unsigned int)(BitsInUnignedInt/);
unsigned int HighBits=(unsigned int)(0xFFFFFFFF)<<(BitsInUnignedInt-OneEighth);
unsigned int hash= ;
unsigned int test= ; while(*str)
{
hash=(hash<<OneEighth)+(*str++);
if((test=hash&HighBits)!=)
{
hash=((hash^(test>>ThreeQuarters))&(~HighBits));
}
} return(hash % M);
} // ELF Hash Function
unsigned int ELFHash(char*str)
{
unsigned int hash= ;
unsigned int x= ; while(*str)
{
hash=(hash<<)+(*str++);
if((x=hash&0xF0000000L)!=)
{
hash^=(x>>);
hash&=~x ;
}
} return(hash % M);
} // BKDR Hash Function
unsigned int BKDRHash(char*str)
{
unsigned int seed= ;// 31 131 1313 13131 131313 etc..
unsigned int hash= ; while(*str)
{
hash=hash*seed+(*str++);
} return(hash % M);
} // SDBM Hash Function
unsigned int SDBMHash(char*str)
{
unsigned int hash= ; while(*str)
{
hash=(*str++)+(hash<<)+(hash<<)-hash ;
} return(hash % M);
} // DJB Hash Function
unsigned int DJBHash(char*str)
{
unsigned int hash= ; while(*str)
{
hash+=(hash<<)+(*str++);
} return(hash % M);
} // AP Hash Function
unsigned int APHash(char*str)
{
unsigned int hash= ;
int i ; for(i=;*str;i++)
{
if((i&)==)
{
hash^=((hash<<)^(*str++)^(hash>>));
}
else
{
hash^=(~((hash<<)^(*str++)^(hash>>)));
}
} return(hash % M);
}
常见hash算法的更多相关文章
- 常见hash算法的原理(转)
常见hash算法的原理 散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表 ...
- 常见hash算法的原理
散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫 ...
- 转 常见hash算法的原理
散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫 ...
- 加密解密(10)常见HASH算法:MD5(128bit),SHA1(160bit)
- 【转】常见的hash算法及其原理
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是 ...
- hash 算法
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是 ...
- Hash算法简介
Hash算法性质 Hash算法用于计算消息摘要(Message Digest),可以将任意长的输入信息快速地转换为固定长度的输出.在区块链中主要利用了Hash算法的三种性质: 抗冲突性(Collisi ...
- 常见的哈希Hash算法 & MD5 & 对称非对称加密 & 海明码
参考 Link 另外,这篇文章也提到了利用Hash碰撞而产生DOS攻击的案例: http://www.cnblogs.com/charlesblc/p/5990475.html DJB的算法实现核心是 ...
- hash算法和常见的hash函数 [转]
Hash,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值. 这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能 会散列成相同的输出,而不 ...
随机推荐
- 数据结构(C++)之Double Linked List实践
//double linked list (type int),the position starts from 0 #include <iostream> using namespace ...
- awk 手册
1. 前言 有关本手册 : 这是一本awk学习指引, 其重点着重于 : l awk 适于解决哪些问题 ? l awk 常见的解题模式为何 ? 为使读者快速掌握awk解题的模 ...
- Yii 1.1 请求报400错误
Yii的action可以带参数,比如: class PostController extends CController { public function actionCreate($categor ...
- OAuth 2 开发人员指南
这是支持OAuth2.0的用户指南.对于OAuth1.0,一切都是不同的,所以看它的用户指南. 本用户指南分为两个部分,第一部分是OAuth2.0提供端(OAuth 2.0 Provider),第二部 ...
- 今天读一读七天学会NodeJS
七天学会NODEJS NodeJS基础 小结 本章介绍了有关NodeJS的基本概念和使用方法,总结起来有以下知识点: NodeJS是一个JS脚本解析器,任何操作系统下安装NodeJS本质上做的事情都是 ...
- Websql,应用程序缓存,WebWorkers,SSE,WebSocket
①什么是 Web Worker? 当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成. web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的 ...
- 你不知道的JavaScript--Item10 闭包(closure)
JavaScript 闭包究竟是什么? 用JavaScript一年多了,闭包总是让人二丈和尚摸不着头脑.陆陆续续接触了一些闭包的知识,也犯过几次因为不理解闭包导致的错误,一年多了资料也看了一些,但还是 ...
- IE8中marquee不显示出滚动效果的解决办法
随着各种软件的升级,我们系统中的IE6也渐渐被淘汰了,目前主流的浏览器一半的用户已经从IE6直接升级到了IE8,虽然给用户更好的体验,上网更快更方便了,但是对网站制作来说,又是个比较麻烦的问题,因为很 ...
- 二逼平衡树 Tyvj 1730 BZOJ3196 Loj#106
树状数组+主席树,模板题,不多说... #include <cstdio> #include <algorithm> #include <cmath> #inclu ...
- VIJOS-P1635 城市连接
嘿嘿嘿,逆向spfa,貌似不难... #include <cstdio> #include <algorithm> #include <cmath> #includ ...