记录几个经典的字符串hash算法,方便以后查看:
推荐一篇文章:这边文章总结了常见的hash 函数
http://www.partow.net/programming/hashfunctions/#
(1)暴雪字符串hash
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#define MAXTABLELEN 102400000
typedef struct _HASHTABLE
{
long nHashA;
long nHashB;
bool bExists;
}HASHTABLE, *PHASHTABLE;
const unsigned long nTableLength = MAXTABLELEN;
unsigned long m_tablelength; // 哈希索引表长度
HASHTABLE *m_HashIndexTable;
unsigned long cryptTable[0x500];
int collc = 0;
int errstr = 0;
void InitCryptTable()
{
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 );
}
}
}
/************************************************************************/
/*函数名:HashString
*功 能:求取哈希值
*返回值:返回hash值
************************************************************************/
unsigned long HashString(char *lpszString, unsigned long dwHashType)
{
unsigned char *key = (unsigned char *)lpszString;
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
int ch;
while(*key != 0)
{
ch = toupper(*key++);
seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}
/************************************************************************/
/*函数名:Hashed
*功 能:检测一个字符串是否被hash过
*返回值:如果存在,返回位置;否则,返回-1
************************************************************************/
unsigned long Hashed(char * lpszString)
{
const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
//不同的字符串三次hash还会碰撞的率无限接近于不可能
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_tablelength;
unsigned long nHashPos = nHashStart;
while (m_HashIndexTable[nHashPos].bExists)
{
if (m_HashIndexTable[nHashPos].nHashA == nHashA && m_HashIndexTable[nHashPos].nHashB == nHashB)
return nHashPos;
else
nHashPos = (nHashPos + 1) % m_tablelength;
if (nHashPos == nHashStart)
break;
}
errstr++;
return -1; //没有找到
}
/************************************************************************/
/*函数名:Hash
*功 能:hash一个字符串
*返回值:成功,返回true;失败,返回false
************************************************************************/
bool Hash(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_tablelength,
nHashPos = nHashStart;
while (m_HashIndexTable[nHashPos].bExists)
{
nHashPos = (nHashPos + 1) % m_tablelength;
if (nHashPos == nHashStart) //一个轮回
{
collc ++;
//hash表中没有空余的位置了,无法完成hash
return false;
}
}
m_HashIndexTable[nHashPos].bExists = true;
m_HashIndexTable[nHashPos].nHashA = nHashA;
m_HashIndexTable[nHashPos].nHashB = nHashB;
return true;
}
int InitHashTable()
{
int i;
InitCryptTable();
m_tablelength = nTableLength;
m_HashIndexTable = (HASHTABLE *)malloc(nTableLength * sizeof(HASHTABLE));
if (NULL == m_HashIndexTable) {
printf("Init HashTable failure!!\n");
return -1;
}
for (i = 0; i < nTableLength; i++ )
{
m_HashIndexTable[i].nHashA = 0;
m_HashIndexTable[i].nHashB = 0;
m_HashIndexTable[i].bExists = false;
}
return 0;
}
void do_test()
{
int count = 0;
FILE *fp;
char url[2048] = {0};
fp = fopen("urllist", "rb+");
if (NULL == fp) {
return;
}
if (InitHashTable()) {
return;
}
while (!feof(fp)) {
fgets(url, 2048, fp);
Hash(url);
count++;
}
printf("count: %d\n", count);
fclose(fp);
}
/*test main*/
int main()
{
do_test();
printf("conflict: %d\n", collc);
printf("not find: %d\n", errstr);
return 0;
}
(2)字符串hash算法 ELFhash
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MOD 10
int ELFhash(char*key)
{
unsigned long h=0;
while(*key)
{
h = (h << 4) + *key++;
unsigned long g = h & 0xF0000000L;
if(g)
h ^= g >> 24;
h &= ~g;
}
return h % MOD;
}
int main(int argc, char **argv)
{
if (argc < 2) {
printf("using %s <string>\n", argv[0]);
return -1;
}
int num = 0;
num = ELFhash(argv[1]);
printf("num is %d\n", num);
}