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. CoreDataStack

  2. Textview在Listview中实现跑马灯效果

    textview添加属性:   android:singleLine="true" 表示单行显示   android:ellipsize="marquee" 设 ...

  3. 【代码笔记】iOS-关于UIFont的一些define

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController ...

  4. iOS 杂笔-23(区分各种空值)

    iOS 杂笔-23(区分各种空值) nil是一个对象指针为空 Nil是一个类指针为空 NULL是基本数据类型为空 NSNull空对象(是可以放在数组里的)

  5. 接口测试中三种传参请求(Map、request、Integer)解析

    注册企业接口传入的是一个request,查询企业接口传入的是一个integer:根据名称和国家名称模糊匹配接口传入的是一个Map:针对三种不同的传参我怎么作接口测试呢? 1 package com.w ...

  6. IntelliJ IDEA 导入新项目以后的简单配置

    首先,配置Maven. 然后,配置Git. 选择自己调试要用的默认浏览器. 进行Edit Configurations 配置: 转载请注明出处! http://www.cnblogs.com/libi ...

  7. .Net魔法堂:提取注释生成API文档

    一.前言 在多人协作的项目中,除了良好的代码规范外,完整的API文档也相当重要.通过文档我们快速了解系统各模块的实际接口,及其使用场景.使用示例,一定程度上降低沟通成本,和减少后期维护中知识遗失等风险 ...

  8. 写在复习MVC后

    MVC的一些 今天把MVC复习了下,包括官方文档以及各种中文博客. 官方文档里面最能说明的问题的图片,相对于传统的MVC,苹果分离了View和Model之间的通信,实现了更好的复用性.我觉得MVC更 ...

  9. Memcache知识点梳理

    Memcache知识点梳理 Memcached概念:    Memcached是一个免费开源的,高性能的,具有分布式对象的缓存系统,它可以用来保存一些经常存取的对象或数据,保存的数据像一张巨大的HAS ...

  10. Access restriction: The type 'RSACipher' is not API

    解决方法: http://stackoverflow.com/questions/860187/access-restriction-on-class-due-to-restriction-on-re ...