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算法的更多相关文章

  1. 常见hash算法的原理(转)

    常见hash算法的原理   散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表 ...

  2. 常见hash算法的原理

    散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫 ...

  3. 转 常见hash算法的原理

    散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫 ...

  4. 加密解密(10)常见HASH算法:MD5(128bit),SHA1(160bit)

  5. 【转】常见的hash算法及其原理

    Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是 ...

  6. hash 算法

    Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是 ...

  7. Hash算法简介

    Hash算法性质 Hash算法用于计算消息摘要(Message Digest),可以将任意长的输入信息快速地转换为固定长度的输出.在区块链中主要利用了Hash算法的三种性质: 抗冲突性(Collisi ...

  8. 常见的哈希Hash算法 & MD5 & 对称非对称加密 & 海明码

    参考 Link 另外,这篇文章也提到了利用Hash碰撞而产生DOS攻击的案例: http://www.cnblogs.com/charlesblc/p/5990475.html DJB的算法实现核心是 ...

  9. hash算法和常见的hash函数 [转]

       Hash,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值. 这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能 会散列成相同的输出,而不 ...

随机推荐

  1. Oracle-11:联合查询

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 联合查询的实际上的意义就是从俩个结果集中拿有特定联系的结果封装为一个结果集 数据库脚本给放一份,供测试使用 c ...

  2. Linux的文本处理工具浅谈-awk sed grep

    Linux的文本处理工具浅谈 awk   老大 [功能说明] 用于文本处理的语言(取行,过滤),支持正则 NR代表行数,$n取某一列,$NF最后一列 NR==20,NR==30 从20行到30行 FS ...

  3. Rest接口和Thymeleaf的两个坑

    spring boot thymeleaf 热部署 在使用spring boot 开发的时候,使用了Thymeleaf 作为前端的模板开发,发现在调试过程中,改动了Thymeleaf模板后,需要重新启 ...

  4. UsernamePasswordAuthenticationToken

    UsernamePasswordAuthenticationToken继承AbstractAuthenticationToken实现Authentication所以当在页面中输入用户名和密码之后首先会 ...

  5. 电梯调度算法---SCAN算法

    请珍惜小编劳动成果,该文章为小编原创,转载请注明出处. 扫描(SCAN)调度算法:总是从磁臂当前位置开始,沿磁臂的移动方向去选择离当前磁臂最近的那个柱面的访问者.如果沿磁臂的方向无请求访问时,就改变磁 ...

  6. 一个简单的例子实现自己的AOP

    AOP是Aspect Oriented Programming的缩写,意思是面向切面编程,与OOP(Object Oriented Programming)面向对象编程对等,都是一种编程思想. 从OO ...

  7. balance.go 源码阅读

    ) //10s +随机毫秒数 后 执行下面代码     for _ = range t {         for _, v := range pBackendSvrs {             i ...

  8. 图解java中的bytebuffer

    因何而写 网上关于bytebuffer的文章真的很多,为何在此还要写一篇呢?主要是基于以下几点考虑 很多人在使用t-io时,还不会bytebuffer,只会照着t-io提供的例子照猫画虎,不利于灵活运 ...

  9. HEOI2018 游记

    day0早上没有跑操,收拾了点东西,带了点吃的,老妈打电话说要给送点厚衣服,好像确实有点冷.上午有考试,说自愿考,然后开到一半就没了,根本没人打啊,打了一道小园丁和老司机,一个一个部分分打,最后T了一 ...

  10. Mysql 上亿级数据导入Hive思路分享

    前提条件: 数据库容量上亿级别,索引只有id,没有创建时间索引 达到目标: 把阿里云RDS Mysql表数据同步到hive中,按照mysql表数据的创建时间日期格式分区,每天一个分区方便查询 每天运行 ...