hashtable

来源:互联网 发布:mac珊瑚红口红效果图 编辑:程序博客网 时间:2024/05/21 03:15

点击打开链接

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

#ifndef __USE_ISOC99
#define inline
#endif

#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




hash.c
--------------------------------------
#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;
}



test.c
--------------------------------------
#ifdef DMALLOC
#include <dmalloc.h>
#else
#include <stdlib.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include "hash.h"

#define maxhash 10

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

int main(int argc, char *argv[])
{
    int i;

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

    memset(key, 0, 20);
    memset(data, 0, 20);
    hashtable *tab = create_hashtable(10);
    for (i = 0; i < maxhash; 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 < maxhash; 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("size %d\n", hash_count(tab));
    hash_free(tab);
    exit(0);
}


编译运行
--------------------------------------
$ gcc test.c hash.c
$ ./a.out 
remove key4
key -> value
key0->the line no: 0
key1->the line no: 1
key2->the line no: 2
key3->the line no: 3
key4->(null)
key5->the line no: 5
key6->the line no: 6
key7->the line no: 7
key8->the line no: 8
key9->the line no: 9

this is ->(null)

key6->the line no: 6
key1->the line no: 1
key0->the line no: 0
key9->the line no: 9
key3->the line no: 3
key8->the line no: 8
key2->the line no: 2
key5->the line no: 5
key7->the line no: 7
size 9



调用函数hash_create()之后创建一个Hash Table
------------------------------------------------------
   
hashtable
|---------------|
| gethash()    
-| lh_strhash()
| compare()    
-| equal_str()
| hashsize     
-| size
| count        
-| 0
| **hashlist   -|------>|------------------|
|---------------|     
--|struct hashentry *| NULL
                        |------------------|
                        |                  |
                        |------------------|
                        |                  |
                        |------------------|
                        |                  |
                        |------------------|
                        |                  |
                        |------------------|
                        |struct hashentry *| NULL
                        |------------------|


调用函数hash_insert()时如果出现冲突,则形成hashentry队列
------------------------------------------------------
   
hashtable
|-------------|
| gethash()   | lh_strhash()
| compare()   | equal_str()
| hashsize    | size
| count       | 2
| **hashlist 
-|---->|------------------|
|-------------|     |struct hashentry *| NULL
                    |------------------|
                    |                  |
                    |------------------|    hashentry     hashentry
                    |                  |-->|---------|   |---------|
                    |------------------|   | *key   
-|   | *key   -|
                    |                  |   | *data 
--|   | *data --|
                    |------------------|   | *next 
--|-->| *next --| NULL
                    |                  |   |---------|   |---------|
                    |------------------|
                    |struct hashentry *| NULL
                    |------------------|

原创粉丝点击