Chinaunix首页 | 论坛 | 博客
  • 博客访问: 418613
  • 博文数量: 66
  • 博客积分: 1416
  • 博客等级: 上尉
  • 技术积分: 922
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-16 10:37
个人简介

高級Oracle DBA,善長Linux系統維運以及Oracle數據庫管理,開發,調優. 具有多年PL/SQL開發經驗.

文章分类

全部博文(66)

文章存档

2015年(9)

2014年(4)

2013年(5)

2010年(1)

2009年(3)

2008年(6)

2007年(30)

2006年(8)

我的朋友

分类: C/C++

2006-12-05 14:58:14

寫了個小小的c語言hash table實現,用單鏈表處理沖突.
lh_strhash 函數是從網上copy的, 已記不清來源了.
 
hash.h
/*
 * Write :Gan Jian Hui
 * Date : 2006/07/18
 * Description : hash table manager
 *
 *
*/
#ifndef _LINUX_GHASH_H_
#define _LINUX_GHASH_H_
#include
/*#include */

#ifndef __USE_ISOC99
#define inline
#endif

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

/*
 * hash function
*/
unsigned int  lh_strhash(void *src) ;

int equal_str(void *k1, void *k2) ;

struct  hashentry ;
struct  _hashtable ;
typedef  struct  _hashtable   hashtable ;
 
/*
* Description :Create hash table
*
* sizeof(struct _hashtable) = 16
* sizeof(void *)= 4
* tab->hashlist size= 4*size
*
*/
hashtable  *hash_create(unsigned int  (*keyfunc)(void *),
   int  (*comparefunc)(void *,void *),
   int size) ;
/*
 *
 *Desc : free hash table
 *
 */
void   hash_free(hashtable *tab) ;
/*
 *Desc : Insert Data to hash table
 *
 *
 */
void hash_insert(void *key, void *data, hashtable *tab) ;
/*
 *
 *Desc :Remove Item from hash table
 *
 *
 */
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
 
/*
 * Write :Gan Jian Hui
 * Date : 2006/07/18
 * Description : hash table manager
 *
 *
*/

#include
#ifdef DMALLOC
#include
#else
#include
#endif
#include "hash.h"
#include "comm.h"
#ifndef __USE_ISOC99
#define inline
#endif
/*
 *
 * list for hash data
 */
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  ;  /* store data */
}   ;

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

/* #define dumplog   printf */
/*
 * hash function
*/
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  ret^=(s[i]<<(i&0x0f));
 return(ret);
}
int equal_str(void *k1, void *k2)
{
    return  (0 == strcmp((char *)k1,(char *)k2)) ;
}
/*
 *
 * end hash function
*/
 
/*
 *Desc : new hash entry
 *
 */
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  ;
}
/*
 *Desc :free hash entry
 *
*/
inline  struct hashentry *hashentry_free(struct hashentry *h)
{
 struct hashentry *next = h->next ;
 DEBUG_DUMP("free hash entry [%p]\n" ,h);
 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 ;
 /* the root */
        if (compare((*root)->key, key)) {
         *root =  hashentry_free(*root) ;
  return 0 ;
 }
 /* the second */
 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 ;
}
 

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

/*
* Description :Create hash table
*
* sizeof(struct _hashtable) = 16
* sizeof(void *)= 4
* tab->hashlist size= 4*size
*
*/
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) ;
 DEBUG_DUMP("hsize:%d  listsize %d\n",len,sizeof(void *)) ;
 if (tab->hashlist == NULL) {
  DEBUG_DUMP("malloc hash table list error\n");
  free(tab) ;
  return NULL;
 }
 memset(tab->hashlist, 0, len ) ;
 for (i=0; ihashlist[i] = NULL ;
 tab->compare = comparefunc ;
 tab->gethash = keyfunc ;
 tab->hashsize = size ;
 tab->count = 0 ;
 return tab ;
}
/*
 *
 *Desc : free hash table
 *
 */
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 ;
}

/*
 *Desc : Insert Data to hash table
 *
 *
 */

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 ) {
          hlist_append(&(tab->hashlist[ index ]),  key, data )  ;
  tab->count ++ ;
 }
}
/*
 *
 *Desc :Remove Item from hash table
 *
 *
 */
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) ;
  }
 }
}
/*
#define   hash_count(tab)          (tab->count)
*/
inline int  hash_count(hashtable *tab)
{
 return tab->count ;
}
 
 
test.c
 
#ifdef DMALLOC
 #include
#else
 #include
#endif
#include
#include
#include "hash.h"

#define maxhash  10
int work(void *key,void *data)
{
 printf("%-8s-> %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  sprintf(key,"key%d",i) ;
  sprintf(data,"the line no: %d",i) ;
  hash_insert((void *)strdup(key), (void *)strdup(data), tab) ;
 }
 
 
/* hash_remove("key3",tab) ;
// */
 printf("remove key4\n") ;  
 hash_remove("key4",tab) ;
 for (i=0 ;i {
  sprintf(key,"key%d",i) ;
  printf("%s->%s\n",key,(char *) hash_value(key,tab));
 }

 hash_remove("key4",tab) ;
 hash_remove("key4",tab) ;
 
 printf("%s->%s\n","this is ", (char *) hash_value("this is ",tab));
 printf("\n\n") ;
 hash_for_each_do(tab,work) ; 
 printf("size %d\n" ,hash_count(tab)) ;
 hash_free(tab) ;
/* exit(EXIT_SUCCESS) ; */
 exit(0) ;
}
阅读(3173) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~