常见hash
来源:互联网 发布:jquery获取form数据 编辑:程序博客网 时间:2024/06/05 14:36
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
解决冲突是一个复杂问题。冲突主要取决于:
(1)散列函数,一个好的散列函数的值应尽可能平均分布。
(2)处理冲突方法。
(3)负载因子的大小。太大不一定就好,而且浪费空间严重,负载因子和散列函数是联动的。
解决冲突的办法:
(1)线性探查法:冲突后,线性向前试探,找到最近的一个空位置。缺点是会出现堆积现象。存取时,可能不是同义词的词也位于探查序列,影响效率。
(2)双散列函数法:在位置d冲突后,再次使用另一个散列函数产生一个与散列表桶容量m互质的数c,依次试探(d+n*c)%m,使探查序列跳跃式分布。
常用的构造散列函数的方法
散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位:
1. 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a•key + b,其中a和b为常数(这种散列函数叫做自身函数)
2. 数字分析法:分析一组数据,比如一组员工的出生年月日,这时我们发现出生年月日的前几位数字大体相同,这样的话,出现冲突的几率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果用后面的数字来构成散列地址,则冲突的几率会明显降低。因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。
3. 平方取中法:取关键字平方后的中间几位作为散列地址。
4. 折叠法:将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址。
5. 随机数法:选择一随机函数,取关键字的随机值作为散列地址,通常用于关键字长度不同的场合。
6. 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p, p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生同义词。
查找的性能分析
查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。影响产生冲突多少有以下三个因素:
1. 散列函数是否均匀;
2. 处理冲突的方法;
3. 散列表的装填因子。
散列表的装填因子定义为:α= 填入表中的元素个数 / 散列表的长度
Hash算法在信息安全方面的应用主要体现在以下的3个方面:
(1) 文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。
(2) 数字签名
Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。 对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。
(3) 鉴权协议
如下的鉴权协议又被称作挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。
/**
* Hash算法大全<br>
* 推荐使用FNV1算法
* @algorithm None
* @author Goodzzp 2006-11-20
* @lastEdit Goodzzp 2006-11-20
* @editDetail Create
*/
public class HashAlgorithms
{
/**
* 加法hash
* @param key 字符串
* @param prime 一个质数
* @return hash结果
*/
public staticint additiveHash(String key,int prime)
{
int hash, i;
for (hash= key.length(), i= 0; i < key.length(); i++)
hash += key.charAt(i);
return (hash% prime);
}
/**
* 旋转hash
* @param key 输入字符串
* @param prime 质数
* @return hash值
*/
public staticint rotatingHash(String key,int prime)
{
int hash, i;
for (hash=key.length(), i=0; i<key.length();++i)
hash = (hash<<4)^(hash>>28)^key.charAt(i);
return (hash% prime);
// return (hash ^ (hash>>10) ^ (hash>>20));
}
// 替代:
// 使用:hash = (hash ^ (hash>>10) ^ (hash>>20)) & mask;
// 替代:hash %= prime;
/**
* MASK值,随便找一个值,最好是质数
*/
static int M_MASK= 0x8765fed1;
/**
* 一次一个hash
* @param key 输入字符串
* @return 输出hash值
*/
public staticint oneByOneHash(String key)
{
int hash, i;
for (hash=0, i=0; i<key.length();++i)
{
hash += key.charAt(i);
hash +=(hash << 10);
hash ^= (hash>> 6);
}
hash += (hash << 3);
hash ^= (hash>> 11);
hash += (hash << 15);
// return (hash & M_MASK);
return hash;
}
/**
* Bernstein's hash
* @param key 输入字节数组
* @param level 初始hash常量
* @return 结果hash
*/
public staticint bernstein(String key)
{
int hash = 0;
int i;
for (i=0; i<key.length();++i) hash= 33*hash + key.charAt(i);
return hash;
}
//
//// Pearson's Hash
// char pearson(char[]key, ub4 len, char tab[256])
// {
// char hash;
// ub4 i;
// for (hash=len, i=0; i<len; ++i)
// hash=tab[hash^key[i]];
// return (hash);
// }
//// CRC Hashing,计算crc,具体代码见其他
// ub4 crc(char *key, ub4 len, ub4 mask, ub4 tab[256])
// {
// ub4 hash, i;
// for (hash=len, i=0; i<len; ++i)
// hash = (hash >> 8) ^ tab[(hash & 0xff) ^ key[i]];
// return (hash & mask);
// }
/**
* Universal Hashing
*/
public staticint universal(char[]key,int mask, int[] tab)
{
int hash = key.length, i, len= key.length;
for (i=0; i<(len<<3); i+=8)
{
char k = key[i>>3];
if ((k&0x01)== 0) hash ^= tab[i+0];
if ((k&0x02)== 0) hash ^= tab[i+1];
if ((k&0x04)== 0) hash ^= tab[i+2];
if ((k&0x08)== 0) hash ^= tab[i+3];
if ((k&0x10)== 0) hash ^= tab[i+4];
if ((k&0x20)== 0) hash ^= tab[i+5];
if ((k&0x40)== 0) hash ^= tab[i+6];
if ((k&0x80)== 0) hash ^= tab[i+7];
}
return (hash& mask);
}
/**
* Zobrist Hashing
*/
public staticint zobrist(char[] key,int mask,int[][] tab)
{
int hash, i;
for (hash=key.length, i=0; i<key.length;++i)
hash ^= tab[i][key[i]];
return (hash& mask);
}
// LOOKUP3
// 见Bob Jenkins(3).c文件
// 32位FNV算法
static int M_SHIFT= 0;
/**
* 32位的FNV算法
* @param data 数组
* @return int值
*/
public staticint FNVHash(byte[] data)
{
int hash =(int)2166136261L;
for(byte b: data)
hash = (hash * 16777619) ^ b;
if (M_SHIFT== 0)
return hash;
return (hash ^(hash >> M_SHIFT))& M_MASK;
}
/**
* 改进的32位FNV算法1
* @param data 数组
* @return int值
*/
public staticint FNVHash1(byte[] data)
{
final int p = 16777619;
int hash =(int)2166136261L;
for(byte b:data)
hash = (hash ^ b) * p;
hash += hash<< 13;
hash ^= hash >> 7;
hash += hash<< 3;
hash ^= hash >> 17;
hash += hash<< 5;
return hash;
}
/**
* 改进的32位FNV算法1
* @param data 字符串
* @return int值
*/
public staticint FNVHash1(String data)
{
final int p = 16777619;
int hash =(int)2166136261L;
for(int i=0;i<data.length();i++)
hash = (hash ^ data.charAt(i))* p;
hash += hash<< 13;
hash ^= hash >> 7;
hash += hash<< 3;
hash ^= hash >> 17;
hash += hash<< 5;
return hash;
}
/**
* Thomas Wang的算法,整数hash
*/
public staticint intHash(int key)
{
key +=~(key << 15);
key ^= (key>>> 10);
key +=(key << 3);
key ^= (key>>> 6);
key +=~(key << 11);
key ^= (key>>> 16);
return key;
}
/**
* RS算法hash
* @param str 字符串
*/
public staticint RSHash(String str)
{
int b = 378551;
int a = 63689;
int hash = 0;
for(int i= 0; i < str.length(); i++)
{
hash = hash * a + str.charAt(i);
a = a * b;
}
return (hash& 0x7FFFFFFF);
}
/* End Of RS Hash Function */
/**
* JS算法
*/
public staticint JSHash(String str)
{
int hash = 1315423911;
for(int i= 0; i < str.length(); i++)
{
hash ^= ((hash << 5)+ str.charAt(i)+ (hash >> 2));
}
return (hash& 0x7FFFFFFF);
}
/* End Of JS Hash Function */
/**
* PJW算法
*/
public staticint PJWHash(String str)
{
int BitsInUnsignedInt = 32;
int ThreeQuarters = (BitsInUnsignedInt * 3) / 4;
int OneEighth = BitsInUnsignedInt / 8;
int HighBits = 0xFFFFFFFF <<(BitsInUnsignedInt - OneEighth);
int hash = 0;
int test= 0;
for(int i= 0; i < str.length();i++)
{
hash = (hash<< OneEighth)+ str.charAt(i);
if((test= hash & HighBits)!= 0)
{
hash = (( hash ^ (test>> ThreeQuarters))& (~HighBits));
}
}
return (hash& 0x7FFFFFFF);
}
/* End Of P. J. Weinberger Hash Function */
/**
* ELF算法
*/
public staticint ELFHash(String str)
{
int hash = 0;
int x = 0;
for(int i= 0; i < str.length(); i++)
{
hash = (hash<< 4)+ str.charAt(i);
if((x= (int)(hash& 0xF0000000L))!= 0)
{
hash ^= (x >> 24);
hash &=~x;
}
}
return (hash& 0x7FFFFFFF);
}
/* End Of ELF Hash Function */
/**
* BKDR算法
*/
public staticint BKDRHash(String str)
{
int seed = 131;// 31 131 1313 13131 131313 etc..
int hash = 0;
for(int i= 0; i < str.length(); i++)
{
hash = (hash* seed) + str.charAt(i);
}
return (hash& 0x7FFFFFFF);
}
/* End Of BKDR Hash Function */
/**
* SDBM算法
*/
public staticint SDBMHash(String str)
{
int hash = 0;
for(int i= 0; i < str.length(); i++)
{
hash = str.charAt(i)+ (hash << 6)+ (hash << 16)- hash;
}
return (hash& 0x7FFFFFFF);
}
/* End Of SDBM Hash Function */
/**
* DJB算法
*/
public staticint DJBHash(String str)
{
int hash = 5381;
for(int i= 0; i < str.length(); i++)
{
hash = ((hash<< 5)+ hash) + str.charAt(i);
}
return (hash& 0x7FFFFFFF);
}
/* End Of DJB Hash Function */
/**
* DEK算法
*/
public staticint DEKHash(String str)
{
int hash = str.length();
for(int i= 0; i < str.length(); i++)
{
hash = ((hash<< 5) ^(hash >> 27)) ^ str.charAt(i);
}
return (hash& 0x7FFFFFFF);
}
/* End Of DEK Hash Function */
/**
* AP算法
*/
public staticint APHash(String str)
{
int hash = 0;
for(int i= 0; i < str.length(); i++)
{
hash ^= ((i & 1)== 0)? ( (hash << 7) ^ str.charAt(i) ^(hash >> 3)):
(~((hash<< 11) ^ str.charAt(i) ^(hash >> 5)));
}
// return (hash & 0x7FFFFFFF);
return hash;
}
/* End Of AP Hash Function */
/**
* JAVA自己带的算法
*/
public staticint java(String str)
{
int h = 0;
int off = 0;
int len = str.length();
for (int i= 0; i < len; i++)
{
h = 31 * h+ str.charAt(off++);
}
return h;
}
/**
* 混合hash算法,输出64位的值
*/
public staticlong mixHash(String str)
{
long hash = str.hashCode();
hash <<= 32;
hash |= FNVHash1(str);
return hash;
}
- 常见hash
- 常见的hash函数
- 常见的字符串Hash
- perl hash 常见用法
- 常见的Hash算法
- perl hash 常见用法
- 常见HASH算法
- perl hash 常见用法
- 常见hash算法介绍
- 常见的Hash算法
- 常见的Hash函数
- 常见的Hash算法
- 常见的Hash算法
- 常见的Hash算法
- 常见的Hash算法
- 常见Hash算法
- 常见Hash算法
- 常见的hash加密
- 表值函数实现Split方法
- scala经典博文
- MySQL执行外部sql脚本文件的命令
- MySQL索引背后的数据结构及算法原理
- IOS开发之XCode快捷键
- 常见hash
- meta缓存(转载)
- IOS 屏幕旋转控制详解-特酷吧
- 有用网址
- java基础编程之查询某一年的二月有多少天(通过Calendar类)
- 02.Add Two Numbers
- C语言获取windows系统的相关信息
- Android MediaProvider--文件管理:必现,文件管理器中新建几个文件夹,批量删除后,连接电脑查看仍有部分文件夹未删除
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通) .