暴雪最快hash算法源碼


中國有句古話"再一再二不能再三再四",看來Blizzard也深得此話的精髓,如果說兩個不同的字符串經過一個哈希算法得到的入口點一致有可能,但用三個不同的哈希算法算出的入口點都一致,那幾乎可以肯定是不可能的事了,這個幾率是1:18889465931478580854784,大概是10的 22.3次方分之一,對一個游戲程序來說足夠安全了。

  1 /*********************************StringHash.h*********************************/
  2 
  3 #pragma once
  4 
  5 #define MAXTABLELEN 1024 // 默認哈希索引表大小 
  6 ////////////////////////////////////////////////////////////////////////// 
  7 // 哈希索引表定義 
  8 typedef struct _HASHTABLE
  9 { 
 10   long nHashA; 
 11   long nHashB; 
 12   bool bExists; 
 13 }HASHTABLE, *PHASHTABLE ;
 14 
 15 class StringHash
 16 {
 17 public:
 18   StringHash(const long nTableLength = MAXTABLELEN);
 19   ~StringHash(void);
 20 private: 
 21   unsigned long cryptTable[0x500]; 
 22   unsigned long m_tablelength; // 哈希索引表長度 
 23   HASHTABLE *m_HashIndexTable; 
 24 private:
 25   void InitCryptTable(); // 對哈希索引表預處理 
 26   unsigned long HashString(const string& lpszString, unsigned long dwHashType); // 求取哈希值 
 27 public:
 28   bool Hash(string url);
 29   unsigned long Hashed(string url); // 檢測url是否被hash過
 30 };
 31 
 32  
 33 
 34 /*********************************StringHash.cpp*********************************/
 35 
 36 #include "StdAfx.h"
 37 #include "StringHash.h"
 38 
 39 StringHash::StringHash(const long nTableLength /*= MAXTABLELEN*/)
 40 {
 41   InitCryptTable(); 
 42   m_tablelength = nTableLength; 
 43   //初始化hash表
 44   m_HashIndexTable = new HASHTABLE[nTableLength]; 
 45   for ( int i = 0; i < nTableLength; i++ ) 
 46   { 
 47     m_HashIndexTable[i].nHashA = -1; 
 48     m_HashIndexTable[i].nHashB = -1; 
 49     m_HashIndexTable[i].bExists = false; 
 50   } 
 51 }
 52 
 53 StringHash::~StringHash(void)
 54 {
 55   //清理內存
 56   if ( NULL != m_HashIndexTable ) 
 57   { 
 58     delete []m_HashIndexTable; 
 59     m_HashIndexTable = NULL; 
 60     m_tablelength = 0; 
 61   } 
 62 }
 63 
 64 /************************************************************************/
 65 /*函數名:InitCryptTable
 66 /*功 能:對哈希索引表預處理 
 67 /*返回值:無
 68 /************************************************************************/
 69 void StringHash::InitCryptTable() 
 70 { 
 71   unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;
 72 
 73   for( index1 = 0; index1 < 0x100; index1++ ) 
 74   { 
 75     for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 ) 
 76     { 
 77       unsigned long temp1, temp2; 
 78       seed = (seed * 125 + 3) % 0x2AAAAB; 
 79       temp1 = (seed & 0xFFFF) << 0x10; 
 80       seed = (seed * 125 + 3) % 0x2AAAAB; 
 81       temp2 = (seed & 0xFFFF); 
 82       cryptTable[index2] = ( temp1 | temp2 ); 
 83     } 
 84   } 
 85 }
 86 
 87 /************************************************************************/
 88 /*函數名:HashString
 89 /*功 能:求取哈希值 
 90 /*返回值:返回hash值
 91 /************************************************************************/
 92 unsigned long StringHash::HashString(const string& lpszString, unsigned long dwHashType) 
 93 { 
 94   unsigned char *key = (unsigned char *)(const_cast<char*>(lpszString.c_str())); 
 95   unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE; 
 96   int ch;
 97 
 98   while(*key != 0) 
 99   { 
100     ch = toupper(*key++);
101 
102     seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2); 
103     seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; 
104   } 
105   return seed1; 
106 }
107 
108 /************************************************************************/
109 /*函數名:Hashed
110 /*功 能:檢測一個字符串是否被hash過
111 /*返回值:如果存在,返回位置;否則,返回-1
112 /************************************************************************/
113 unsigned long StringHash::Hashed(string lpszString)
114 
115 { 
116   const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2; 
117   //不同的字符串三次hash還會碰撞的幾率無限接近於不可能
118   unsigned long nHash = HashString(lpszString, HASH_OFFSET); 
119   unsigned long nHashA = HashString(lpszString, HASH_A); 
120   unsigned long nHashB = HashString(lpszString, HASH_B); 
121   unsigned long nHashStart = nHash % m_tablelength, 
122   nHashPos = nHashStart;
123 
124   while ( m_HashIndexTable[nHashPos].bExists) 
125   { 
126   if (m_HashIndexTable[nHashPos].nHashA == nHashA && m_HashIndexTable[nHashPos].nHashB == nHashB)
127     return nHashPos; 
128   else 
129   nHashPos = (nHashPos + 1) % m_tablelength;
130 
131   if (nHashPos == nHashStart) 
132   break; 
133   }
134 
135   return -1; //沒有找到 
136 }
137 
138 /************************************************************************/
139 /*函數名:Hash
140 /*功 能:hash一個字符串 
141 /*返回值:成功,返回true;失敗,返回false
142 /************************************************************************/
143 bool StringHash::Hash(string lpszString)
144 { 
145   const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2; 
146   unsigned long nHash = HashString(lpszString, HASH_OFFSET); 
147   unsigned long nHashA = HashString(lpszString, HASH_A); 
148   unsigned long nHashB = HashString(lpszString, HASH_B); 
149   unsigned long nHashStart = nHash % m_tablelength, 
150   nHashPos = nHashStart;
151 
152   while ( m_HashIndexTable[nHashPos].bExists) 
153   { 
154     nHashPos = (nHashPos + 1) % m_tablelength; 
155     if (nHashPos == nHashStart) //一個輪回 
156     { 
157       //hash表中沒有空余的位置了,無法完成hash
158       return false; 
159     } 
160   } 
161   m_HashIndexTable[nHashPos].bExists = true; 
162   m_HashIndexTable[nHashPos].nHashA = nHashA; 
163   m_HashIndexTable[nHashPos].nHashB = nHashB;
164 
165   return true; 
166 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM