My Window,Your Bridge!

关于技术,关于生活!


C hash结构的实现.



非同步的hash结构的简单实现。

根据不同的key用hash函数计算出在数组中的位置,数组中保存的是一个链表结构的结构,不同key在hash值相同的情况下,可以用链表来控制在内存中的位置。

hashtable.h文件.


/*****************************************
 *  FILE   : hashtable.h
 *  DATE   : 2008/01/06
 *  AUTHOR : ZhangLiHai
 * ***************************************/
#ifndef HASHTABLE_H_
#define HASHTABLE_H_
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct __hash_entry hash_entry;
typedef struct __hash_entry* p_hash_entry;
typedef struct __hash_table hashtable;
typedef struct __hash_table* p_hashtable;

typedef int BOOL;
#define TRUE 1
#define FALSE 0
struct __hash_entry{
         p_hash_entry next;//next entry
         unsigned int hash_code;//key hash_code...
         const char* key; //key..
         const void* value;//value object
         int klen; //entry size.
};
struct __hash_table{
        int capacity;// array length.
        int size;//cur size
        unsigned int (*hash_code_fp)(const char*);//hash_code function pointer.
        void (*value_free_fp)(void*);
        void (*key_free_fp)(char*);
        p_hash_entry *array; //entry array;
};

//foreach function pointer.
typedef  BOOL (*hash_foreach_fp)(p_hash_entry);

/***********************
 * 
 * 创建一个hashtable指针
 * 
 * *********************/
p_hashtable new_hashtab();

p_hash_entry new_entry();

/***************************************
 * 
 * 将key,value放入hash结构里面
 * 
 * *************************************/
BOOL hash_put(p_hashtable,const char*, const void*);


/******************************************
 * 
 * 
 * 根据key返回一个void *
 * 
 * 
 * ******************************************/
void* hash_get(p_hashtable,const char*);

/*****************************************
 * 
 * 重新分配hash空间
 * 
 * 重新规划元素的位置 
 * ***************************************/
BOOL hash_resize(p_hashtable );



/****************************************
 * 
 * 
 * hash code算法的默认实现~
 * 
 * 
 * **************************************/
unsigned int hash_code_fp_default(const char*);


/**************
 * 
 * 
 * 删除某个key下的值
 * 
 * 
 * 
 * **********************/
BOOL hash_remove_key(p_hashtable,  const char*);

/********************
 * 
 * 清除hash里面的所有数据,但是保存hashtable本身
 * 
 * **********************/
BOOL hash_data_clear(p_hashtable );


/*****************
 *
 * 看某个key是否在hash里面
 * 
 * ************************/
BOOL hash_contains_key(p_hashtable,  const char*);
/**************************
 * 迭代函数
 * 一个是清楚数据,另一个没有清除
 * ******************/
void hash_foreach_no_clear(p_hashtable,hash_foreach_fp);
void hash_foreach_clear(p_hashtable,hash_foreach_fp);
/********************************
 * 
 * 两个默认的free方法,调用stdlib的free函数
 * 
 * *******************************/
void std_key_free(char *);
void std_value_free(void *);

/************************
 * 
 * 回收一个hashtable指针
 * 
 * 如果里面的value需要回收,则传入一个函数指针
 * 
 * ************************/
BOOL free_hashtab(p_hashtable );

#endif /*HASHTABLE_H_*/


hashtable.c文件包含测试

 /*****************************************
 *  FILE   : hashtable.c
 *  DATE   : 2008/01/06
 *  AUTHOR : ZhangLiHai
 * ***************************************/
#include "hashtable.h"

#define MAX_SIZE 1024
#define HASH_IND(h,n) ((h)%(n))

p_hashtable new_hashtab(){
  p_hashtable tab;
       tab = (p_hashtable)malloc(sizeof(struct __hash_table));
       printf("new hashtable \n");
       tab->size=0;
       tab->capacity=MAX_SIZE;
       tab->array=(p_hash_entry*)calloc(tab->capacity,sizeof(p_hash_entry));
       printf("new hashtable->array pointer. \n");
       tab->hash_code_fp=&hash_code_fp_default;
       tab->value_free_fp=NULL;
       tab->key_free_fp=NULL;
        return tab;        
}

p_hash_entry new_entry(){
  p_hash_entry this;
             this = (p_hash_entry)malloc(sizeof(struct __hash_entry));
             this->hash_code=0;
             this->key=NULL;
             this->klen=0;
             this->next=NULL;
             this->value=NULL;
             printf("new entry . \n");
           return this;
}
unsigned int hash_code_fp_default(const char* key){
  register unsigned  int hash;        
        for(hash=0;*key;key++)
           hash = *key+hash*31;
  return abs(hash);
}

void std_key_free(char *p){
        if(p)
          free(p);        
}

void std_value_free(void *p){
        if(p)
          free(p);
}


BOOL hash_remove_key(p_hashtable tab,  const char* key)
{
        void* value;
        p_hash_entry e,prev,next;
    int hash,ind;
    if(!tab||!key)return FALSE;
            hash=tab->hash_code_fp(key);
            ind=HASH_IND(hash,tab->capacity);
        e=tab->array[ind];
        prev=e;
        next=NULL;
        while(e)
        {
                 next=e->next;
             if(e->hash_code==hash && !strcmp(key,e->key))
             {
                 tab->size--;
                          if(e==prev)
                              tab->array[ind]=next;
                           else
                              prev->next=next;
                          break;   
             }else{
                prev=e;
                e=next;        
             }        
        }
        if(e){
             if(tab->key_free_fp)tab->key_free_fp((char *)e->key);
             if(tab->value_free_fp)tab->value_free_fp((void *)e->value);        
             free(e);
             printf("free entry\n");
             return TRUE;
        }
        return FALSE;
}

BOOL hash_data_clear(p_hashtable tab)
{
        p_hash_entry p;
        p_hash_entry q;
        int i=0;
        if(!tab)return FALSE;
        for(i=0;i<tab->capacity;i++)
        {
                for(p=tab->array[i];p;p=q)
                {
                        q=p->next;
                 if(tab->key_free_fp)tab->key_free_fp((char*)p->key);
                     if(tab->value_free_fp)tab->value_free_fp((void*)p->value);
                free(p);
                printf("free hash entry \n");
                }
                tab->array[i]=0;
        }
        tab->size=0;
  return TRUE;        
}

BOOL free_hashtab(p_hashtable tab)
{
    hash_data_clear(tab);
        free(tab->array);
        printf("free--hash->array.\n");
        tab->array=NULL;
        tab->capacity=0;
        free(tab);
        printf("free--hashtab.\n");
        tab=NULL;
  return TRUE;        
}

void* hash_get(tab,key)
p_hashtable tab;
const char* key;
{
   p_hash_entry e;
   int hash;
   if(!tab||!key)return NULL;
   hash=tab->hash_code_fp(key);
   for(e=tab->array[HASH_IND(hash,tab->capacity)];e;e=e->next)
   {
              if(e->hash_code==hash&&!strcmp(e->key,key))
              {
                return ((void *)e->value);
              }
   }
   return NULL;        
}

BOOL hash_put(p_hashtable tab,const char* key, const void* value){
        int hash ;
        int ind;
        p_hash_entry next_entry;
        p_hash_entry entry;
        if(!tab||!key||!value)return FALSE;
     hash = tab->hash_code_fp(key);
     ind = HASH_IND(hash,tab->capacity);
     next_entry=tab->array[ind];
     entry=new_entry();
     entry->hash_code=hash;
     entry->key=key;
     entry->value=value;
     entry->next=next_entry;
     entry->klen=strlen(key);
     tab->array[ind]=entry;
     tab->size++;
     if((tab->size*3/2)>tab->capacity)
        hash_resize(tab);
   return TRUE;        
}

BOOL hash_resize(p_hashtable tab){
        p_hash_entry* new_array;
        p_hash_entry entry,next;
        int new_capacity,i,ind;
        new_capacity=tab->capacity*2;
        new_array=(p_hash_entry*)calloc(new_capacity,sizeof(p_hash_entry));
        for(i=0;i<tab->capacity;i++){
          if(entry=tab->array[i]){
                        do{
                                 tab->array[i]=0;
                                  next = entry->next;
                              ind=HASH_IND(entry->hash_code,new_capacity);
                              entry->next=new_array[ind];
                              new_array[ind]=entry;
                              entry=next;
                          }while(entry);
          }
        }
        free(tab->array);
        printf("resize free old array \n");
        printf("hash_resize to %d\n",new_capacity);
        tab->array=new_array;
        tab->capacity=new_capacity;
 return TRUE;        
}

BOOL hash_contains_key(p_hashtable tab,  const char* key){
        if(!tab||!key)return FALSE;
   return (hash_get(tab,key)!=NULL);        
}


void hash_foreach_no_clear(p_hashtable tab,hash_foreach_fp fp){
        int i;
        if(!tab||!fp)return;
        for(i=0;i<tab->capacity;i++)
        {
             if(tab->array[i])
              if(!fp(tab->array[i]))
                return;        
        }
}
void hash_foreach_clear(p_hashtable tab,hash_foreach_fp fp)
{
        p_hash_entry p;
        p_hash_entry q;
        int i=0;
        if(!tab||!fp)return;
        for(i=0;i<tab->capacity;i++)
        {
                for(p=tab->array[i];p;p=q)
                {
                        q=p->next;
                        fp(p);
                 if(tab->key_free_fp)tab->key_free_fp((char*)p->key);
                     if(tab->value_free_fp)tab->value_free_fp((void*)p->value);
                free(p);
                printf("free hash entry \n");
                }
                tab->array[i]=0;
        }
        tab->size=0;
}

unsigned int hash_code_fp_simple(const char* key){
  return 101;        
}

BOOL hash_foreach_fp_simple(p_hash_entry e){
         printf("foreach : key=%s,value=%s\n",e->key,e->value);
  return TRUE;        
}
int main(){
        int i;
        char *key,*value;
        char key_buf[11];
     p_hashtable tab = new_hashtab();
     tab->key_free_fp=&std_key_free;
     tab->value_free_fp=&std_value_free;
     tab->hash_code_fp=&hash_code_fp_default;
     for(i=0;i<100;i++)
     {
         key=(char *)malloc(sizeof(char)*11);
         value=(char *)malloc(sizeof(char)*11);
         memset(key,0,11);
         memset(value,0,11);
         sprintf(key,"key_%d",i);
         sprintf(value,"val_%d",i);
         hash_put(tab,key,value);        
     }
    hash_foreach_no_clear(tab,&hash_foreach_fp_simple);
    hash_remove_key(tab,"key_2");
    for(i=10;i<tab->size;i++)
     {
         memset(key_buf,0,11);
         sprintf(key_buf,"key_%d",i);
         printf("get==>key=%s,val=%s\n",key_buf,hash_get(tab,key_buf));        
     }
    hash_data_clear(tab);
    printf("hash.size : %d\n",tab->size);
    free_hashtab(tab);
        return 0;        
}



该日志的引用地址:

发表评论:



日历

网站目录

搜索

Powered By O-Blog | Template Modified By FengSe

Copyright 2003-2007 ZhangLiHai.Com.All Rights Reserved.