记录几个常用的hash函数

记录几个经典的字符串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);
}

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值