Hashtable实现

#include <string.h>
#ifdef DMALLOC
#include <dmalloc.h>
#else
#include <stdlib.h>
#endif
#include "hash.h"
#ifndef __USE_ISOC99
#define inline
#endif

struct hashentry
{
    void *key;
    void *data;
    struct hashentry *next;
};

struct _hashtable
{
    unsigned int (*gethash)(void *);
    int (*compare)(void *, void *);
    int hashsize;
    int count;
    struct hashentry **hashlist;
};

#define hashindex(key, tab) ((tab->gethash)(key) % (tab->hashsize -1))

unsigned int lh_strhash(void *src)
{
    int i, l;
    unsigned long ret = 0;
    unsigned short *s;
    char *str = (char *)src;
    if (str == NULL)
        return(0);
    l = (strlen(str) + 1) / 2;
    s = (unsigned short *)str;

    for (i = 0; i < l; i++)
        ret ^= s[i]<<(i&0x0f);

    return(ret);
}

int equal_str(void *k1, void *k2)
{
    return (0 == strcmp((char *)k1, (char *)k2));
}

inline struct hashentry *hashentry_new(void *key, void *data)
{
    struct hashentry *new = malloc(sizeof(struct hashentry));
    new->key = key;
    new->data = data;
    new->next = NULL;
    return new;
}

void hlist_append(struct hashentry **root, void *key, void *data)
{
    struct hashentry *l, *pos;
    l = hashentry_new(key, data);
    if (*root == NULL) {
        *root = l;
    } else {
        for(pos = *root; pos->next != NULL; pos = pos->next);
            pos->next = l;
    }
}

int hlist_update(struct hashentry *root, void *key, void *data,
        int (*compare)(void *, void *))
{
    struct hashentry *pos;
    for(pos = root; pos != NULL; pos = pos->next ) {
        if ( compare(key, pos->key) ) {
            free(pos->data);
            pos->data = data;
            free(key);
            return 0;
        }
    }
    return -1;
}

inline struct hashentry *hashentry_free(struct hashentry *h)
{
    struct hashentry *next = h->next;
    free(h->key);
    free(h->data);
    free(h);
    h = NULL;
    return (next);
}

int hlist_remove(struct hashentry **root, void *key,
                 int (*compare)(void *,void *))
{
    struct hashentry *pos ,*prev;

    if (NULL == *root) return -1;

    if (compare((*root)->key, key)) {
        *root = hashentry_free(*root);
        return 0;
    }

    prev = *root;
    for (pos = prev->next; NULL != pos; pos = pos->next) {
        if (compare(pos->key, key)) {
            prev->next = hashentry_free(pos);
            return 0;
        }
        prev = pos;
    }
    return -1;
}

hashtable *hash_create(unsigned int (*keyfunc)(void *),
                       int (*comparefunc)(void *, void *),
                       int size)
{
    int len = sizeof(struct hashentry *) * size;
    int i;
    hashtable *tab = malloc( sizeof(hashtable) );
    memset(tab, 0, sizeof(hashtable));
    tab->hashlist = malloc(len);

    if (tab->hashlist == NULL) {
        free(tab);
        return NULL;
    }

    memset(tab->hashlist, 0, len );
    for (i = 0; i < size; i++)
        tab->hashlist[i] = NULL ;

    tab->compare = comparefunc;
    tab->gethash = keyfunc;
    tab->hashsize = size;
    tab->count = 0;
    return tab;
}

void hash_free(hashtable *tab)
{
    int i;
    struct hashentry *pos;

    for (i = 0; i < tab->hashsize; i++)
        for (pos = tab->hashlist[i]; NULL != pos; pos = hashentry_free(pos));

    free(tab->hashlist);
    free(tab);
    tab =NULL;
}

void hash_insert(void *key, void *data, hashtable *tab)
{
    unsigned int index = hashindex(key, tab);
    struct hashentry *root = tab->hashlist[index];

    if ( hlist_update(root, key, data, tab->compare ) != 0 ) { //(1)

        hlist_append(&(tab->hashlist[index]), key, data );
        tab->count++;
    }
}

//(1) 查看Hash Table中是否存在键值为key的项,如果有则替换该键值所对应的value,否则调用hlist_append为key, data生成新的hashentry并插入相应的队列中。


void hash_remove(void *key, hashtable *tab)
{
    unsigned int index = hashindex(key, tab);
    if (hlist_remove(&(tab->hashlist[index]), key, tab->compare) == 0) {
        tab->count--;
    }
}

void *hash_value(void *key, hashtable *tab)
{
    struct hashentry *pos;
    unsigned int index = hashindex(key, tab);
    for (pos = tab->hashlist[index]; NULL != pos; pos = pos->next) {
        if (tab->compare(key, pos->key)) {
            return (pos->data);
        }
    }
    return NULL;
}


void hash_for_each_do(hashtable *tab, int(cb)(void *, void *))
{
    int i = 0;
    struct hashentry *pos;
    for (i = 0; i < tab->hashsize; i++) {
        for (pos = tab->hashlist[i]; NULL != pos; pos = pos->next ) {
            cb(pos->key, pos->data);
        }
    }
}

inline int hash_count(hashtable *tab)
{
    return tab->count;
}



/*hash.h*/



#ifndef _LINUX_GHASH_H_
#define _LINUX_GHASH_H_
#include <string.h>

#ifndef __USE_ISOC99
#define inline
#endif
//Tomoka Asagi 麻木明香

#define create_hashtable(hsize) \
hash_create(lh_strhash, equal_str, hsize)

unsigned int lh_strhash(void *src);
int equal_str(void *k1, void *k2);

struct hashentry;
struct _hashtable;
typedef struct _hashtable hashtable;


hashtable *hash_create(unsigned int (*keyfunc)(void *),
int (*comparefunc)(void *,void *),
int size);
void hash_free(hashtable *tab);
void hash_insert(void *key, void *data, hashtable *tab);
void hash_remove(void *key, hashtable *tab);
void *hash_value(void *key, hashtable *tab);
void hash_for_each_do(hashtable *tab, int (cb)(void *, void *));
int hash_count(hashtable *tab);

#endif


/*hashfunc.c*/



unsigned int RSHash(char* str, unsigned int len)
{
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = hash * a + (*str);
a = a * b;
}
return hash;
}
/* End Of RS Hash Function */

unsigned int JSHash(char* str, unsigned int len)
{
unsigned int hash = 1315423911;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash ^= ((hash << 5) + (*str) + (hash >> 2));
}
return hash;
}
/* End Of JS Hash Function */

unsigned int PJWHash(char* str, unsigned int len)
{
const unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
const unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt * 3) / 4);
const unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8);
const unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
unsigned int hash = 0;
unsigned int test = 0;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = (hash << OneEighth) + (*str);
if((test = hash & HighBits) != 0)
{
hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));
}
}
return hash;
}
/* End Of P. J. Weinberger Hash Function */

unsigned int ELFHash(char* str, unsigned int len)
{
unsigned int hash = 0;
unsigned int x = 0;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = (hash << 4) + (*str);
if((x = hash & 0xF0000000L) != 0)
{
hash ^= (x >> 24);
}
hash &= ~x;
}
return hash;
}
/* End Of ELF Hash Function */

unsigned int BKDRHash(char* str, unsigned int len)
{
unsigned int seed = 131; /* 31 131 1313 13131 131313 etc.. */
unsigned int hash = 0;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = (hash * seed) + (*str);
}
return hash;
}
/* End Of BKDR Hash Function */

unsigned int SDBMHash(char* str, unsigned int len)
{
unsigned int hash = 0;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = (*str) + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
/* End Of SDBM Hash Function */

unsigned int DJBHash(char* str, unsigned int len)
{
unsigned int hash = 5381;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = ((hash << 5) + hash) + (*str);
}
return hash;
}
/* End Of DJB Hash Function */

unsigned int DEKHash(char* str, unsigned int len)
{
unsigned int hash = len;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = ((hash << 5) ^ (hash >> 27)) ^ (*str);
}
return hash;
}
/* End Of DEK Hash Function */

unsigned int BPHash(char* str, unsigned int len)
{
unsigned int hash = 0;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash = hash << 7 ^ (*str);
}
return hash;
}
/* End Of BP Hash Function */

unsigned int FNVHash(char* str, unsigned int len)
{
const unsigned int fnv_prime = 0x811C9DC5;
unsigned int hash = 0;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash *= fnv_prime;
hash ^= (*str);
}
return hash;
}
/* End Of FNV Hash Function */

unsigned int APHash(char* str, unsigned int len)
{
unsigned int hash = 0xAAAAAAAA;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (*str) * (hash >> 3)) :
(~((hash << 11) + (*str) ^ (hash >> 5)));
}
return hash;
}
/* End Of AP Hash Function */





/*main.c*/



#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <time.h>
#include "hash.h"
#include "mysql/include/mysql.h"

#define hash_max 1000000

unsigned char get_value();
int my_rand(int min, int max);
unsigned char get_intbits(int a);
//哈希
unsigned int hash_func(char* str, unsigned int len)
{
unsigned int hash = 0xAAAAAAAA;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (*str) * (hash >> 3)) :
(~((hash << 11) + (*str) ^ (hash >> 5)));
}
return hash;
}

int work(void *key, void *data)
{
printf("%s->%s\n",(char *)key, (char *)data);
return 0;
}

int main()
{
int i;

char key[20];
char data[20];

memset(key, 0, 20);
memset(data, 0, 20);
hashtable *tab = create_hashtable(hash_max);
for (i = 0; i <hash_max; i++) {
//srand(time(NULL));
//sprintf(key, "key%d", rand()+i);
sprintf(key, "key%d", i);
sprintf(data, "the line no: %d", i);
hash_insert((void *)strdup(key), (void *)strdup(data), tab);
}

/*printf("remove key4\n");
hash_remove("key4", tab);
printf("key -> value\n");
for (i = 0; i < 10; i++) {
sprintf(key, "key%d", i);
printf("%s->%s\n", key, (char *)hash_value(key, tab));
}
printf("\n");

printf("%s->%s\n", "this is ", (char *)hash_value("this is ", tab));

printf("\n");*/
//hash_for_each_do(tab, work);
printf("current i %d\n", i);
printf("size %d\n", hash_count(tab));
hash_free(tab);
exit(0);
}

unsigned char get_value()
{
if (rand() % 2 == 0)
{
return 1;
}
else
{
return 0;
}
}

int my_rand(int min, int max)
{
return rand();
}

unsigned char get_intbits(int a)
{
int i = 1;
while(1)
{
if (a < 10) return i;
a = (int)a/10;
i++;
}
}


下面的是测试

/*test.c*/


#include "zhash.h"

int main(int argc, char **argv)
{
hashtable *tab = hash_create(MAXHASHSIZE);
unsigned int mac[ETH_ALEN]={0x00,0x68,0x30,0x3b,0x2a,0x56};
unsigned int ipaddr[4]={0xC0,0xA8,0x01,0x01};
unsigned int mac1[ETH_ALEN]={0x00,0x69,0x30,0x3b,0x2a,0x42};
unsigned int ipaddr1[4]={0xC0,0xA8,0x01,0x02};
char key[5];
// char key1[5];
memset(key,0,5);
// memset(key1,0,5);
sprintf(key,"%.2x%.2x",mac[4],mac[5]);
hash_insert((void *)key,(void *)ipaddr,(void *)mac,tab);
sprintf(key,"%.2x%.2x",mac1[4],mac1[5]);
hash_insert((void *)key,(void *)ipaddr1,(void *)mac1,tab);
hash_print(tab);
return 0;
}


//另外的HASH算法



#include "zhash.h"

unsigned int lh_strhash(void * src)
{
int i, l;
unsigned long ret = 0;
unsigned short *s;
char *str = (char *)src;
if (str == NULL)
return(0);
l = (strlen(str) + 1) / 2;
s = (unsigned short *)str;

for (i = 0; i < l; i++)
ret ^= s[i]<<(i&0x0f);
return(ret);
}

int equal_str(void *k1, void *k2)
{
return (0 == strcmp((char *)k1, (char *)k2));
}
hashentry *hlist_new(void *key, void *ipaddr, void *mac)
{
hashentry *new = (hashentry *)malloc(sizeof(hashentry));

new->key = key;
new->ipaddr = ipaddr;
new->mac = mac;
new->next = NULL;
return new;
}

void hlist_append(hashentry **root, void *key, void *ipaddr, void *mac)
{
hashentry *new, *pos;
new = hlist_new(key, ipaddr, mac);
if(*root == NULL)
{
*root = new;
}
else
{
pos = *root;
while(pos->next != NULL)
pos = pos->next;
pos->next = new;
}
}
bool hlist_update(hashentry *root, void *key,void *ipaddr,void *mac,int (*compare)(void *,void *))
{
hashentry *pos;
for(pos = root; pos != NULL; pos = pos->next)
{
if(compare(key,pos->key))
{
// free(pos->ipaddr);
// free(pos->mac);
pos->ipaddr = ipaddr;
pos->mac = mac;
// free(key);
return TRUE;
}
}
return FALSE;
}

void hash_insert(void *key, void *ipaddr, void *mac, hashtable *tab)
{
unsigned int index = hashindex(key, tab);
hashentry *root = tab->hashlist[index];
if(!(hlist_update(root, key, ipaddr, mac, tab->compare)))
{
hlist_append(&tab->hashlist[index],key,ipaddr, mac);
tab->count++;
}
}

hashtable *hash_create_t(unsigned int (*keyfunc)(void *),
int (*comparefunc)(void *,void *),
int size)
{
int i;
int len = sizeof(hashentry *) * size;
hashtable *tab = (hashtable *)malloc(sizeof(hashtable));
memset (tab, 0, sizeof(hashtable *));

tab->hashlist = (hashentry**)malloc(len);
if(tab->hashlist == NULL)
{
free(tab);
return NULL;
}
memset(tab->hashlist,0,len);

for(i = 0; i<size; i++)
{
tab->hashlist[i] = NULL;
}
tab->gethash = keyfunc;
tab->compare = comparefunc;
tab->hashsize = size;
tab->count = 0;

return tab;
}

void hash_print(hashtable *tab)
{
int i;
int *p;
hashentry *temp;
printf("index\t%-20s\t%-20s\n","mac","ipaddr");
for(i = 0; i < MAXHASHSIZE; i++)
{
temp = tab->hashlist[i];
if(temp == NULL)
printf("%-d\t%-20s\t%-20s\n",i,"NULL","NULL");
else
printf("%d\t",i);
while(temp != NULL)
{
p = (int *)(temp->mac);
printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t",p[0],p[1],p[2],p[3],p[4],p[5]);
p = (int *)(temp->ipaddr);
const char *format = (temp->next == NULL)?("%d.%d.%d.%d\n"):("%d.%d.%d.%d -->\n\t");
printf(format,p[0],p[1],p[2],p[3]);
temp = temp->next;
}
}
}
/*
void help()
{
printf("command: \n");
printf(" -insert\n");
printf("\t--usage: insert mac ipaddr eg. insert 00:11:22:33:44:55 192.168.0.1\n");
printf("\t--description: insert mac,ip to hash table,mac divided by \":\",and ip by \".\"\n");
printf(" -del\n");
printf("\t--usage:del key eg.del 4455\n");
printf("\t--description: delete from hash table,key is the last 16 bits of mac\n");
printf(" -print\n");
printf("\t--usage: print\n");
printf("\t--description: print all over the hash table\n");
}*/


/*zhash.h头文件*/
posted on 2011-02-15 11:24 闲云blog 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/nbblog/archive/2011/02/15/1954995.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值