1. 程式人生 > >幾種常見雜湊函式程式碼實現

幾種常見雜湊函式程式碼實現

幾種常見雜湊函式的C程式碼實現

雜湊演算法將任意長度的二進位制值對映為較短的固定長度的二進位制值,這個小的二進位制值稱為雜湊值。雜湊值是一段資料唯一且極其緊湊的數值表示形式。如果雜湊一段明文而且哪怕只更改該段落的一個字母,隨後的雜湊都將產生不同的值。要找到雜湊為同一個值的兩個不同的輸入,在計算上是不可能的,所以資料的雜湊值可以檢驗資料的完整性。一般用於快速查詢和加密演算法。——[百度百科]

在網上各處蒐集了一些關於雜湊函式具體實現的程式碼,多出自大家之手,非原創,在實際測試中這些演算法沒有太大的效能差異。

  1. RS
    Robert SedgwicksAlgorithms in C

    一書中得到了。原文作者Arash Partow已經添加了一些簡單的優化的演算法,以加快其雜湊過程。

    unsigned int RSHash(char* str, unsigned int len)
    {
    unsigned int b    = 378551;
    unsigned int a    = 63689;
    unsigned int hash = 0;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash = hash * a + (*str);
      a    = a * b;
    }
    
    return hash;
    }
  2. JS
    Justin Sobel

    寫的一個位操作的雜湊函式。

    unsigned int JSHash(char* str, unsigned int len)
    {
    unsigned int hash = 1315423911;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash ^= ((hash << 5) + (*str) + (hash >> 2));
    }
    
    return hash;
  3. PJW
    該雜湊演算法是基於貝爾實驗室的彼得J溫伯格的的研究。在Compilers一書中(原則,技術和工具),建議採用這個演算法的雜湊函式的雜湊方法。

    unsigned int PJWHash(char* str, unsigned int len)
    {
    const unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
    const unsigned int ThreeQuarters     = (unsigned int)((BitsInUnsignedInt  * 3) / 4);
    const unsigned int OneEighth         = (unsigned int)(BitsInUnsignedInt / 8);
    const unsigned int HighBits          = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
    unsigned int hash              = 0;
    unsigned int test              = 0;
    unsigned int i                 = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash = (hash << OneEighth) + (*str);
    
      if((test = hash & HighBits)  != 0)
      {
         hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));
      }
    }
    
    return hash;
  4. ELF
    和PJW很相似,在Unix系統中使用的較多。

    unsigned int ELFHash(char* str, unsigned int len)
    {
    unsigned int hash = 0;
    unsigned int x    = 0;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash = (hash << 4) + (*str);
      if((x = hash & 0xF0000000L) != 0)
      {
         hash ^= (x >> 24);
      }
      hash &= ~x;
    }
    
    return hash;
    }
  5. BKDR
    這個演算法來自Brian KernighanDennis RitchieThe C programming Language。這是一個很簡單的雜湊演算法,使用了一系列奇怪的數字,形式如31,3131,31…31,看上去和DJB演算法很相似。

    unsigned int BKDRHash(char* str, unsigned int len)
    {
    unsigned int seed = 131; /* 31 131 1313 13131 131313 etc.. */
    unsigned int hash = 0;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash = (hash * seed) + (*str);
    }
    
    return hash;
    }
  6. SDBM
    這個演算法在開源的SDBM中使用,似乎對很多不同型別的資料都能得到不錯的分佈。

    unsigned int SDBMHash(char* str, unsigned int len)
    {
    unsigned int hash = 0;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash = (*str) + (hash << 6) + (hash << 16) - hash;
    }
    
    return hash;
    }
  7. DJB
    這個演算法是Daniel J.Bernstein 教授發明的,是目前公佈的最有效的雜湊函式。

    unsigned int DJBHash(char* str, unsigned int len)
    {
    unsigned int hash = 5381;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash = ((hash << 5) + hash) + (*str);
    }
    
    return hash;
    }
  8. DEK
    由偉大的Knuth 在《程式設計的藝術 第三卷》的第六章排序和搜尋中給出。

    unsigned int DEKHash(char* str, unsigned int len)
    {
    unsigned int hash = len;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash = ((hash << 5) ^ (hash >> 27)) ^ (*str);
    }
    return hash;
    }
  9. AP
    這是原文作者Arash Partow 貢獻的一個雜湊函式。

    unsigned int APHash(char* str, unsigned int len)
    {
    unsigned int hash = 0xAAAAAAAA;
    unsigned int i    = 0;
    
    for(i = 0; i < len; str++, i++)
    {
      hash ^= ((i & 1) == 0) ? (  (hash <<  7) ^ (*str) * (hash >> 3)) :
                               (~((hash << 11) + ((*str) ^ (hash >> 5))));
    }
    
    return hash;
    }