zc_hashtable.h

/**
* hashtable
*/ #ifndef __zc_hashtable_h
#define __zc_hashtable_h typedef struct zc_hashtable_entry_s {
unsigned int hash_key;
void *key;
void *value;
struct zc_hashtable_entry_s *prev;
struct zc_hashtable_entry_s *next;
} zc_hashtable_entry_t; typedef struct zc_hashtable_s zc_hashtable_t; typedef unsigned int (*zc_hashtable_hash_fn) (const void *key);
typedef int (*zc_hashtable_equal_fn) (const void *key1, const void *key2);
typedef void(*zc_hashtable_del_fn) (void *kv); zc_hashtable_t *zc_hashtable_new(size_t a_size,
zc_hashtable_hash_fn hash_fn,
zc_hashtable_equal_fn equal_fn,
zc_hashtable_del_fn key_del_fn,
zc_hashtable_del_fn value_del_fn); void zc_hashtable_del(zc_hashtable_t *a_table);
void zc_hashtable_clean(zc_hashtable_t *a_table);
int zc_hashtable_put(zc_hashtable_t *a_table, void *a_key, void *a_value); zc_hashtable_entry_t *zc_hashtable_get_entry(zc_hashtable_t *a_table, const void *a_key); void *zc_hashtable_get(zc_hashtable_t *a_table, const void *a_key);
void zc_hashtable_remove(zc_hashtable_t *a_table, const void *a_key); zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t *a_table);
zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t *a_table, zc_hashtable_entry_t *a_entry); struct zc_hashtable_s {
//记录当前element的个数
size_t nelem; zc_hashtable_entry_t **tab;
size_t tab_size; zc_hashtable_hash_fn hash;
zc_hashtable_equal_fn equal;
zc_hashtable_del_fn key_del;
zc_hashtable_del_fn value_del;
}; #define zc_hashtable_foreach(a_table, a_entry)\
for(a_entry = zc_hashtable_begin(a_table); a_entry; a_entry = zc_hashtable_next(a_table, a_entry)) unsigned int zc_hashtable_str_hash(const void *str);
int zc_hashtable_str_equal(const void *key1, const void *key2); #endif

zc_hashtable.c

#include <stdlib.h>
#include <errno.h>
#include <pthread.h> #include "zc_defs.h"
#include "zc_hashtable.h" //struct zc_hashtable_s {
// //记录当前element的个数
// size_t nelem;
//
// zc_hashtable_entry_t **tab;
// size_t tab_size;
//
// zc_hashtable_hash_fn hash;
// zc_hashtable_equal_fn equal;
// zc_hashtable_del_fn key_del;
// zc_hashtable_del_fn value_del;
//}; zc_hashtable_t *zc_hashtable_new(size_t a_size,
zc_hashtable_hash_fn hash,
zc_hashtable_equal_fn equal,
zc_hashtable_del_fn key_del,
zc_hashtable_del_fn value_del){ zc_hashtable_t *a_table;
a_table = (zc_hashtable_t *)calloc(, sizeof(zc_hashtable_t));
if(!a_table){
zc_error("calloc fail, errno[%d]", errno);
return NULL;
} a_table->tab = (zc_hashtable_entry_t **)calloc(a_size, sizeof(zc_hashtable_entry_t *));
if(!a_table->tab){
zc_error("calloc fail, errno[%d]", errno);
free(a_table);
return NULL;
}
a_table->tab_size = a_size; a_table->nelem = ;
a_table->hash = hash;
a_table->equal = equal; //these two could be NULL
a_table->key_del = key_del;
a_table->value_del = value_del; return a_table;
} void zc_hashtable_del(zc_hashtable_t *a_table){
size_t i;
zc_hashtable_entry_t *p;
zc_hashtable_entry_t *q; if(!a_table){
zc_error("a_table[%p] is NULL, just do nothing", a_table);
return ;
} for(i = ; i < a_table->tab_size; i++){
//hash conflic
for(p = (a_table->tab)[i]; p; p = q){
q = p->next;
if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
}
free(p);
}
}
if(a_table->tab){
free(a_table->tab);
}
free(a_table); return;
} void zc_hashtable_clean(zc_hashtable_t *a_table){
size_t i;
zc_hashtable_entry_t *p, *q; for(i = ; i < a_table->tab_size; i++){
for(p = (a_table->tab)[i]; p; p = q){
q = p->next;
if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
}
free(p);
}
(a_table->tab)[i] = NULL;
}
a_table->nelem = ; return;
} static int zc_hashtable_rehash(zc_hashtable_t *a_table){
size_t i, j, tab_size;
zc_hashtable_entry_t **tab;
zc_hashtable_entry_t *p;
zc_hashtable_entry_t *q; tab_size = * a_table->tab_size;
tab = calloc(tab_size, sizeof(zc_hashtable_t *));
if(!tab){
zc_error("calloc fail, errno[%d]", errno);
return -;
} for(i = ; i < a_table->tab_size; i++){
//优化
for(p = a_table->tab[i]; p; p = q){
q = p->next; p->prev = NULL;
p->next = NULL;
j = p->hash_key % tab_size;
if(tab[j]){
tab[j]->prev = p;
p->next = tab[j];
}
tab[j] = p;
}
}
free(a_table->tab);
a_table->tab = tab;
a_table->tab_size = tab_size; return ;
} void *zc_hashtable_get(zc_hashtable_t *a_table, const void *a_key){
size_t i;
zc_hashtable_entry_t *p = NULL; i = a_table->hash(a_key) % a_table->tab_size;
for(p = a_table->tab[i]; p; p = p->next){
if(a_table->equal(a_key, p->key)){
return p->value;
}
}
return NULL;
} int zc_hashtable_put(zc_hashtable_t *a_table, void *a_key, void *a_value){
int rc;
size_t i;
zc_hashtable_entry_t *p = NULL; i = a_table->hash(a_key) % a_table->tab_size;
for(p = a_table->tab[i]; p; p = p->next){
if(a_table->equal(a_key, p->key)){
break;
}
} //a_table->tab[i] have value
if(p){
if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
}
p->key = a_key;
p->value = a_value;
return ;
}else{
if(a_table->nelem > a_table->tab_size * 1.3){
rc = zc_hashtable_rehash(a_table);
if(rc){
zc_error("rehash fail");
return -;
}
}
//如果sizeof(zc_hashtable_entry_t *) 会造成free失败
p = calloc(, sizeof(zc_hashtable_entry_t));
if(!p){
zc_error("calloc fail, errno[%d]", errno);
return -;
} p->hash_key = a_table->hash(a_key);
p->key = a_key;
p->value = a_value;
p->next = NULL;
p->prev = NULL; i = p->hash_key % a_table->tab_size;
//has value
if(a_table->tab[i]){
a_table->tab[i]->prev = p;
p->next = a_table->tab[i];
}
a_table->tab[i] = p;
a_table->nelem++;
} return ;
} void zc_hashtable_remove(zc_hashtable_t *a_table, const void *a_key){
size_t i;
zc_hashtable_entry_t *p; if(!a_table || !a_key){
zc_error("a_table[%p] or a_key[%p] is NULL, just do nothing", a_table, a_key);
return ;
}
i = a_table->hash(a_key) % a_table->tab_size;
for(p = a_table->tab[i]; p; p = p->next){
if(a_table->equal(a_key, p->key)){
break;
}
} if(!p){
zc_error("p[%p] is not found in hashtable", p);
return;
} if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
} if(p->next){
p->next->prev = p->prev;
}
if(p->prev){
p->prev->next = p->next;
}else{
//notice
a_table->tab[i] = p->next;
} free(p);
a_table->nelem--; return;
} zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t *a_table){
size_t i;
zc_hashtable_entry_t *p;
for(i= ; i < a_table->tab_size; i++){
for(p = a_table->tab[i]; p; p->next){
if(p){
return p;
}
}
}
printf("%d\n", i);
return NULL;
} zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t *a_table, zc_hashtable_entry_t *a_entry){
size_t i, j; if(a_entry->next){
return a_entry->next;
} i = a_entry->hash_key % a_table->tab_size; for(j = i + ; j < a_table->tab_size; j++){
if(a_table->tab[j]){
return a_table->tab[j];
}
} return NULL;
} /**************************************************hash、equal**********************************************/ int zc_hashtable_str_equal(const void *key1, const void *key2){
return (STRCMP((const char *)key1, ==, (const char *)key2));
} unsigned int zc_hashtable_str_hash(const void *str){
size_t h = ;
const char *p = (const char *)str; while(*p != '\0'){
h = ((h << ) + h) + (*p++); /* hash * 33 + c*/
} return h;
}

测试

#include <stdio.h>

#include "zc_defs.h"
#include "zc_hashtable.c"
#include "zc_profile.c" void myfree(void *kv){ } int main(){
zc_hashtable_t *a_table;
zc_hashtable_entry_t *a_entry; a_table = zc_hashtable_new(,
zc_hashtable_str_hash,
zc_hashtable_str_equal,
myfree,myfree
); zc_hashtable_put(a_table, "aaa", "");
zc_hashtable_put(a_table, "bbb", "");
zc_hashtable_put(a_table, "ccc", ""); zc_hashtable_foreach(a_table, a_entry){
printf("k[%s], v[%s]\n", a_entry->key, a_entry->value);
} printf("getv[%s]\n", (char *)zc_hashtable_get(a_table, "ccc")); zc_hashtable_remove(a_table, "ccc"); zc_hashtable_foreach(a_table, a_entry){
printf("k[%s], v[%s]\n", a_entry->key, a_entry->value);
} zc_hashtable_remove(a_table, NULL);
zc_hashtable_del(NULL); zc_hashtable_del(a_table); return ;
}

zlog学习笔记(zc_hashtable)的更多相关文章

  1. zlog学习笔记(mdc)

    mdc.h #ifndef __zlog_mdc_h #define __zlog_mdc_h #include "zc_defs.h" typedef struct zlog_m ...

  2. zlog学习笔记(level_list)

    level_list.h /** * */ #ifndef __zlog_level_list_h #define __zlog_level_list_h zc_arraylist_t *zlog_l ...

  3. zlog学习笔记(level)

    level.h /** * */ #ifndef __zlog_level_h #define __zlog_level_h #include "stdio.h" #include ...

  4. zlog学习笔记(zc_arraylist)

    zc_arraylist.h /** * 实现类似列表的功能 * */ #ifndef __zc_arraylist_h #define __zc_arraylist_h #define ARRAY_ ...

  5. zlog学习笔记(zc_profile)

    zc_profile.h #ifndef __zlog_profile_h #define __zlog_profile_h #define EMPTY() #define zc_assert(exp ...

  6. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  7. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  8. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  9. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

随机推荐

  1. 属性观察器willSet与didSet

    willSet与didSet是swift特有的,就是监听属性值的变化,但有一个小注意点. willSet与didSet调用时机:对象创建后的第一次赋值时开始调用.也就是说,初始化时(包含重载的init ...

  2. 为什么Java中字符串是不可变的

    前言 在Java中,字符串是一个不可变的类,一个不可变的类指的是它的实例对象不能被修改,所有关于这个对象的信息在这个对象被创建时已初始化且不能被改变. 不可变类有很多优势,这篇文章总结了字符串类之所以 ...

  3. MyEclipse Servers视窗出现“Could not create the view: An unexpected exception was thrown”错误的解决办法

    打开myeclipse所在的wordspace文件夹,在下面子文件夹 .metadata\.plugins\org.eclipse.core.runtime\.settings删除 com.genui ...

  4. CMPP3.0 长短信实现方案

    长短信息:是指超过70个汉字,140个字节的信息内容 一.CMPP协议相关字段分析 CMPP协议具体部分请参考<中国移动互联网短信网关接口协议(V3.0.0).doc> CMPP_SUBM ...

  5. 编写一个Java应用程序,该应用程序包括2个类:Print类和主类E。Print 类里有一个方法output()功能是输出100 ~ 999之间的所有水仙花数(各位数字的 立方和等于这个三位数本身,如: 371 = 33 + 73 + 13。)在主类E的main方法中来 测试类Print

    package zuoye; public class print { void output() { System.out.println("100-999之间的水仙花数是:") ...

  6. 获取下拉框的value和值

    jsp: <td class="formItem_content"> <select name="label" id = "labe ...

  7. PHP生成器Generators

    下文的第一个逐行读取文件例子用三种方式实现;普通方法,迭代器和生成器,比较了他们的优缺点,很好,可以引用到自己的代码中 ,支持的php版本(PHP 5 >= 5.5.0) 后面的yield讲解, ...

  8. WPF自定义空心文字

    首先创建一个自定义控件,继承自FrameworkElement,“Generic.xaml”中可以不添加样式. 要自定义空心文字,要用到绘制格式化文本FormattedText类.FormattedT ...

  9. VMworld 2015 感受:VMware “Ready For Any”

    今年有机会参加在旧金山举行的 VMworld 2015.今天是正式开始的第一天.争取每天写一篇文章分享所见所听所感.第一天的主要活动,包括上午的 General Session,由 VMware 的几 ...

  10. AI(Adobe Illustrator)简单入门——骷髅

    成果: 步骤如下: 一.椭圆工具画正圆 按住shift+alt画一个正圆. 二.圆角矩形工具画矩形 用圆角矩形工具画一个矩形,然后全选水平垂直对齐. 三.画眼睛 利用椭圆工具画一只眼睛,然后按住alt ...