记录几个经典的字符串hash算法

(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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值