理解Blizzard Hash

來源:互聯網
上載者:User

詳細資料:http://www.oschina.net/code/snippet_99767_1217

 

1.一個Hash演算法首先要有一個Hash表:

 

//////////////////////////////////////////////////////////////////////////<br />// 雜湊索引表定義<br />typedef struct _HASHTABLE<br />{<br />long nHashA;<br />long nHashB;<br />bool bExists;<br />}HASHTABLE, *PHASHTABLE ;<br />m_tablelength = nTableLength;<br />//初始化hash表<br />m_HashIndexTable = new HASHTABLE[nTableLength];<br />for ( int i = 0; i < nTableLength; i++ )<br />{<br />m_HashIndexTable[i].nHashA = -1;<br />m_HashIndexTable[i].nHashB = -1;<br />m_HashIndexTable[i].bExists = false;<br />}  

 

2.還要有一個壓縮演算法,把字串壓縮成32位不帶正負號的整數:

unsigned long StringHash::HashString(const string& lpszString, unsigned long dwHashType)<br />{<br />unsigned char *key = (unsigned char *)(const_cast<char*>(lpszString.c_str()));<br />unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;<br />int ch;<br />while(*key != 0)<br />{<br />ch = toupper(*key++);<br />seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);<br />seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;<br />}<br />return seed1;<br />}  

3.在上面那個壓縮演算法中有一個cryptTable,我們要先把它處理一下:

void StringHash::InitCryptTable()<br />{<br />unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;<br />for( index1 = 0; index1 < 0x100; index1++ )<br />{<br />for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 )<br />{<br />unsigned long temp1, temp2;<br />seed = (seed * 125 + 3) % 0x2AAAAB;<br />temp1 = (seed & 0xFFFF) << 0x10;<br />seed = (seed * 125 + 3) % 0x2AAAAB;<br />temp2 = (seed & 0xFFFF);<br />cryptTable[index2] = ( temp1 | temp2 );<br />}<br />}<br />}  

4.現在就可以Hash一個字串了,我們調用了三次壓縮演算法,擷取了三個hash值,第一個hash值用來計算其在hash表中的索引,還有兩個用來處理碰撞情況(兩個不同的字串三次hash的結果是一樣的機率基本為0)

bool StringHash::Hash(<br />string lpszString, //url<br />const PLinkNode node //url 對應節點<br />)<br />{<br />const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;<br />unsigned long nHash = HashString(lpszString, HASH_OFFSET);<br />unsigned long nHashA = HashString(lpszString, HASH_A);<br />unsigned long nHashB = HashString(lpszString, HASH_B);<br />unsigned long nHashStart = nHash % m_tablelength,<br />nHashPos = nHashStart;<br />while ( m_HashIndexTable[nHashPos].bExists)<br />{<br />nHashPos = (nHashPos + 1) % m_tablelength;<br />if (nHashPos == nHashStart) //一個輪迴<br />{<br />//hash表中沒有空餘的位置了,無法完成hash<br />return false;<br />}<br />}<br />m_HashIndexTable[nHashPos].bExists = true;<br />m_HashIndexTable[nHashPos].nHashA = nHashA;<br />m_HashIndexTable[nHashPos].nHashB = nHashB;<br />return true;<br />}  

5.我們還需要一個介面,用來判斷一個字串是否被hash過

unsigned long StringHash::Hashed(const string& url)<br />{<br />const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;<br />//不同的字串三次hash還會碰撞的幾率無限接近於不可能<br />unsigned long nHash = HashString(url, HASH_OFFSET);<br />unsigned long nHashA = HashString(url, HASH_A);<br />unsigned long nHashB = HashString(url, HASH_B);<br />unsigned long nHashStart = nHash % m_tablelength,<br />nHashPos = nHashStart;<br />while ( m_HashIndexTable[nHashPos].bExists)<br />{<br />if (m_HashIndexTable[nHashPos].nHashA == nHashA && m_HashIndexTable[nHashPos].nHashB == nHashB)<br />return nHashPos;<br />else<br />nHashPos = (nHashPos + 1) % m_tablelength;<br />if (nHashPos == nHashStart)<br />break;<br />}<br />return -1; //沒有找到<br />}  

至此,一個簡單的字串hash演算法就完成了。

 

---------------------------------------------------------------------------------------------------------------------------------------------------

總結:

 

一開始對下面的代碼不是很理解

while ( m_HashIndexTable[nHashPos].bExists)<br />{<br />nHashPos = (nHashPos + 1) % m_tablelength;<br />if (nHashPos == nHashStart) //一個輪迴<br />{<br />//hash表中沒有空餘的位置了,無法完成hash<br />return false;<br />}<br />} 

其實,就是一個hash值與其他的碰撞了,那就先來後到,挑下面相鄰的地方;這並不會影響Hashed()的匹配,匹配時也是按照這樣的方法,並且還要匹配那兩個hash值,有點像從一個房間開始,挨個敲門,看裡面是不是要找的人!

所以說這是一個空間換時間的演算法,hash表越大,發生碰撞的可能性就越小,演算法複雜度就越接近於O(1);

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.