StringHash.H
#ifndef __STRING_HASH_H__
#define __STRING_HASH_H__
// Definition of MPQHashTable
struct MPQHashTable
{
long nHashA;
long nHashB;
bool bExists;
};
#define CRYPT_TABLE_LENGTH (256 * 5)
#define MAX_TABLE_LENGTH 1024
class StringHash
{
private:
unsigned long m_pCryptTable[CRYPT_TABLE_LENGTH];
unsigned long m_nTableLength;
MPQHashTable* m_pHashTable;
private:
void InitCryptTable();
unsigned long HashString(const char* lpszString, unsigned long hashType);
public:
StringHash(unsigned long tableLength = MAX_TABLE_LENGTH);
~StringHash();
bool Hash(const char* lpszString);
unsigned long Hashed(const char* lpszString);
unsigned long getHashTableLength();
};
#endif
StringHash.CPP
#include "StringHash.h"
#include <ctype.h>
#include <stdlib.h>
// Initialize the crypt array
void StringHash::InitCryptTable()
{
unsigned long seed = 0x00100001;
for (int i = 0; i < 256; ++i)
{
for (int j = i, k = 0; k < 5; ++k, j += 256)
{
seed = (seed * 125 + 3) % 0x2AAAAB;
unsigned long tmp = (seed & 0xFFFF) << 0x10;
seed = (seed * 125 + 3) % 0x2AAAAB;
m_pCryptTable[j] = tmp | (seed & 0xFFFF);
}
}
}
StringHash::StringHash(unsigned long tableLength)
{
m_nTableLength = tableLength;
m_pHashTable = new MPQHashTable[m_nTableLength];
InitCryptTable();
for (unsigned long i = 0; i < m_nTableLength; ++i)
{
m_pHashTable[i].nHashA = -1;
m_pHashTable[i].nHashB = -1;
m_pHashTable[i].bExists = false;
}
}
StringHash::~StringHash()
{
if (NULL != m_pHashTable)
{
delete[] m_pHashTable;
m_pHashTable = NULL;
m_nTableLength = 0;
}
}
// The one-way hash function
unsigned long StringHash::HashString(const char*lpszString, unsigned long hashType)
{
unsigned char* key = (unsigned char*)lpszString;
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
int ch;
while (*key != 0)
{
ch = toupper(*key++);
seed1 = m_pCryptTable[hashType << 8] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}
// Hash a string to the hash table
bool StringHash::Hash(const char* lpszString)
{
const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
unsigned long nHash = HashString(lpszString, HASH_OFFSET);
unsigned long nHashA = HashString(lpszString, HASH_A);
unsigned long nHashB = HashString(lpszString, HASH_B);
unsigned long nHashStart = nHash % m_nTableLength;
unsigned long nHashPos = nHashStart;
while (m_pHashTable[nHashPos].bExists)
{
nHashPos = (nHashPos + 1) % m_nTableLength;
if (nHashPos == nHashStart)
{
return false;
}
}
m_pHashTable[nHashPos].bExists = true;
m_pHashTable[nHashPos].nHashA = nHashA;
m_pHashTable[nHashPos].nHashB = nHashB;
return true;
}
// Find a string in the hash table, if it exists then return
// the index of the string, else return -1
unsigned long StringHash::Hashed(const char* lpszString)
{
const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
unsigned long nHash = HashString(lpszString, HASH_OFFSET);
unsigned long nHashA = HashString(lpszString, HASH_A);
unsigned long nHashB = HashString(lpszString, HASH_B);
unsigned long nHashStart = nHash % m_nTableLength;
unsigned long nHashPos = nHashStart;
while (m_pHashTable[nHashPos].bExists)
{
if (m_pHashTable[nHashPos].nHashA == nHashA && m_pHashTable[nHashPos].nHashB == nHashB)
{
return nHashPos;
}
else
{
nHashPos = (nHashPos + 1) % m_nTableLength;
}
if (nHashPos == nHashStart)
{
break;
}
}
return -1;
}
unsigned long StringHash::getHashTableLength()
{
return m_nTableLength;
}
测试函数:
#include "StringHash.h"
#include <iostream>
using namespace std;
int main()
{
char* str1 = "StringHash.h";
char* str2 = "StringHash.cpp";
StringHash hasher(20);
cout << "Length of Hash Table: " << hasher.getHashTableLength() << endl;
cout << "Hash \"" << str1 << "\": " << boolalpha << hasher.Hash(str1) << endl;
cout << "Hash \"" << str2 << "\": " << boolalpha << hasher.Hash(str2) << endl;
cout << "Checking ..." << endl;
cout << "Position of \"" << str1 << "\": " << hasher.Hashed(str1) << endl;
cout << "Position of \"" << str1 << "\": " << hasher.Hashed(str2) << endl;
return 0;
}
参考: http://sfsrealm.hopto.org/inside_mopaq/chapter2.htm