常见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;
     }

0 0
原创粉丝点击