哈希算法--暴雪的mpq技术

摘自论坛:http://bbs.csdn.net/topics/300172062,先保存下来

 

强烈的推荐你使用暴雪的mpq技术
我在个人机器上实现过4000万条字符串存储,碰撞很小
需要代码的话,请留下你的邮箱

这里留下我以前用过的一个小程序,稍做修给后应该可以满足你的要求:

#include <iostream>
 using namespace std;
 
#define nTableSize  40000000
 #define nMaxStrLen  20
 
unsigned long cryptTable[0x1000];
 typedef struct _MPQHASHTABLE
 {    
 char bExists;
 }MPQHASHTABLE;
 
MPQHASHTABLE    HashTable[nTableSize];
 int                HashATable[nTableSize];
 int                HashBTable[nTableSize]; 
 
char            data[nTableSize][nMaxStrLen];
 
class CHashForMpq
 {

 public:
  int insert_string(const char *string_in)
  {
   const int HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;//定义哈希类型
 /*计算lpszString字符串经过解析后应该放入或者查询各表的数据*/
  unsigned int nHash = HashString(string_in, HASH_OFFSET);//生成要放入hash表中的数据
 unsigned int nHashA = HashString(string_in, HASH_A);//要放入hashA表中的数据
 unsigned int nHashB = HashString(string_in, HASH_B);//要放入hashB表中的数据
 unsigned int nHashStart = nHash % nTableSize;//计算起始查询位置
 unsigned int nHashPos = nHashStart;//初始化实际查询到的位置
     
  while (HashTable[nHashPos].bExists)//发生了碰撞
{ 
 //校验碰撞原因
 if (HashATable[nHashPos]  == nHashA && HashBTable[nHashPos] == nHashB) 
 break; //原始数据发生了重复,可能的情况:1.发生了错误,2.我们执行的是查询
 else 
  nHashPos = (nHashPos + 1) % nTableSize;//说明数据没有重复,但原来的位置上有数据,也就是发生了碰撞的情况,所以将实际位置偏移
       
  if (nHashPos == nHashStart) 
  {
 cout<<"表已满,无法插入数据"<<endl;
  return 0; 
  }
 }
  /*插入的情况*/
  if (!HashTable[nHashPos].bExists && (strlen(string_in) < nMaxStrLen))
  {   
  HashATable[nHashPos] = nHashA;
  HashBTable[nHashPos] = nHashB;
  strcpy(data[nHashPos], string_in);
  HashTable[nHashPos].bExists = 1;
            cout<<"字符串"<<string_in<<"插入成功,位于"<<nHashPos<<endl;
  }
  else
  {
  if(HashTable[nHashPos].bExists)
 cout<<"字符串"<<string_in<<"已存在于表中,无法插入"<<endl;
  else
 cout<<"字符串"<<string_in<<"长度超标,无法插入"<<endl;
  }
  return nHashPos;

  }
 
  int search_string(const char *string_in)
  {
   const int HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;//定义哈希类型
 /*计算lpszString字符串经过解析后应该放入或者查询各表的数据*/
  unsigned int nHash = HashString(string_in, HASH_OFFSET);//生成要放入hash表中的数据
 unsigned int nHashA = HashString(string_in, HASH_A);//要放入hashA表中的数据
 unsigned int nHashB = HashString(string_in, HASH_B);//要放入hashB表中的数据
 unsigned int nHashStart = nHash % nTableSize;//计算起始查询位置
 unsigned int nHashPos = nHashStart;//初始化实际查询到的位置
         
  while (HashTable[nHashPos].bExists)//发生了碰撞
{ 
 //校验碰撞原因
 if (HashATable[nHashPos]  == nHashA && HashBTable[nHashPos] == nHashB) 
 break; //原始数据发生了重复,可能的情况:1.发生了错误,2.我们执行的是查询
 else 
  nHashPos = (nHashPos + 1) % nTableSize;//说明数据没有重复,但原来的位置上有数据,也就是发生了碰撞的情况,所以将实际位置偏移
       
  if (nHashPos == nHashStart) 
  cout<<"字符串"<<string_in<<"不在表中"<<endl;
  return 0; 
 }
  if(strlen(data[nHashPos]))
  {
  cout<<"字符串"<<string_in<<"在表中"<<nHashPos<<endl;
  return nHashPos;
  }
  else
 
 cout<<"字符串"<<string_in<<"不在表中"<<endl;

  }
 



/*生成密码表*/
void prepareCryptTable()
 { 
 unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;
  
 for( index1 = 0; index1 < 0x100; index1++ )
 { 
  for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 )
 { 
  unsigned long temp1, temp2;
  seed = (seed * 125 + 3) % 0x2AAAAB;
  temp1 = (seed & 0xFFFF) << 0x10;
  seed = (seed * 125 + 3) % 0x2AAAAB;
  temp2 = (seed & 0xFFFF);
  cryptTable[index2] = ( temp1 | temp2 ); 
 } 
  } 
 }
 private:
     /*按照dwHashType定义的类型取得字符串lpszFileName的各项hash值*/
unsigned long HashString(const char *lpszFileName, unsigned long dwHashType )
 { 
  unsigned char *key  = (unsigned char *)lpszFileName;
  unsigned long seed1 = 0x7FED7FED;
  unsigned long seed2 = 0xEEEEEEEE;
  int ch;
 
 while( *key != 0 )
  { 
 ch = *key++;
 seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
     seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; 
  }
 
 return seed1; 
  }
 
};
 
void main()
 {
 CHashForMpq cHashForMpq;
 cHashForMpq.prepareCryptTable();
     
     cHashForMpq.insert_string("abcdefghijklmnopqrstuvwxyz");
     cHashForMpq.insert_string("abcd");
     cHashForMpq.insert_string("ab");
 cHashForMpq.insert_string("ab");
 
cHashForMpq.search_string("abcd");
 
    cHashForMpq.search_string("efd");
 
   getchar();
 } 


 

你可能感兴趣的:(哈希算法--暴雪的mpq技术)