摘自论坛: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(); }