一种hashtable 实现的使用介绍

阅读代码上瘾了么?又看到一份代码,觉得很符合自己的风格,就贴上来。

/* implementation of a simple hash table
* -- thread safe functions as *_safe()
* -- resolve collisions by chaining
* Direct comments, concerns, questions, bugs to:
* kulesh [squiggly] isis.poly.edu
*/
该实现考虑到了线程安排,与STL的hashtable思想一致,都是基于resolve collisions by chaining(用开链解决冲突)。

hash节点定义

struct hash_entry {
struct list_head list;
unsigned
char *key;
unsigned
int keylen;
};
/* a hash_table contains buckets full of hash_entries (See above).
* keycmp() is used to compare the keys of hash_entries
*/
struct hash_table {
struct hash_entry *table; //竖向的vector 容量为b

unsigned
int buckets;
pthread_mutex_t
*bucket_locks;//锁 容量为b

pthread_mutex_t
lock;
keycmp_ptr keycmp;

/* private variables */
unsigned
int __ht_i;
struct list_head *pos;
};

private域的作用是遍历用的。

锁对外界是不可见的,对于要上锁的话,库提供了__safe()函数来实现。例如insert函数

hash_table_insert
/* insert_hash_table()
* @h: &struct hash_table hash table to insert hash_entry into
* @e: &struct hash_entry
* Description: inserts @e into @h using @e->key as key. not thread-safe.
*/
void hash_table_insert(struct hash_table *h,
struct hash_entry *e,
const unsigned char *key, unsigned int len);


/* insert_hash_table_safe()
* @h: &struct hash_table hash table to insert hash_entry into
* @e: &struct hash_entry
* @key: use key to insert the hash_entry
* @len: length of the key
* Description: inserts @e into @h using @e->key as key. thread-safe.
*/
void hash_table_insert_safe(struct hash_table *h,
struct hash_entry *e,
const unsigned char *key, unsigned int len);

请参看注释。下面代码不给出注释了。

重要接口函数如下

int hash_table_init(struct hash_table *h,
            unsigned
int b,
keycmp_ptr keycmp);
void hash_table_finit(struct hash_table *h);

int hash_entry_init(struct hash_entry *e,
const unsigned char *str,
            unsigned
int len);
void hash_entry_finit(struct hash_entry *e);

void hash_table_insert(struct hash_table *h,
             
struct hash_entry *e,
              
const unsigned char *key,
              unsigned
int len);

struct hash_entry *hash_table_lookup_key(const struct hash_table *h,
                        
const unsigned char *str,
                        unsigned
int len);

struct hash_entry *hash_table_del_key(struct hash_table *h,
                      
const char *str,
                      unsigned
int len);

类似于linux list实现的宏接口

for_each
/**
* hash_entry - get the user data for this entry
* @ptr: the &struct hash_entry pointer
* @type: the type of the user data (e.g. struct my_data) embedded in this entry
* @member: the name of the hash_entry within the struct (e.g. entry)
*/
hash_entry(ptr, type, member);

/*
* @hentry: &struct hash_entry
* @htable: &struct hash_table
*/
#define hash_table_for_each(hentry, htable)

/*
* @hentry: &struct hash_entry
* @htable: &struct hash_table
* @pos: &struct list_head
* @hti: unsigned int
*/
hash_table_for_each_safe(hentry, htable, pos, hti)

个人觉得,还可以开放的接口(其实现添加了static inline),这个注释里面提到了,传递来的struct hash_entry,而不是str类型。当然传递的应该是一个有hash_entry_init生成的合法struct hash_entry。

/* same as hash_table_lookup_key() but this function takes a valid hash_entry as input.
* a valid hash_entry is the one that has key, len set appropriately. in other words, a
* hash_entry that is the output of hash_entry_init()
*/
struct hash_entry *hash_table_lookup_hash_entry(const struct hash_table *h,
        const struct hash_entry *e)

源代码中给出了示例。与list实现数据域与节点域分离的原则,要引用hashtable,直接包含其即可,实现数据域与指针域的结合。

定义如下

struct myitem {
struct hash_entry entry;
unsigned
char foo[32];
unsigned
int bar;
};

注意作者这里为了方便,用foo保存了hash_entry中的key信息。

初始化hash_table

struct hash_table mytable;
/* initialize the hash table with 10 buckets */
hash_table_init(
&mytable, 10, NULL);
插入hash_entry
tmp = (struct myitem *)malloc(sizeof(struct myitem));
/**一些初始化*/
hash_table_insert(
&mytable, &tmp->entry, str, len);

遍历节点

hash_table_for_each(hentry, &mytable) {
tmp
= hash_entry(hentry, struct myitem, entry);
fprintf(stdout,
"key: %s[%d] (%d)\n", tmp->foo, tmp->bar,
hash_table_hash_code(
&mytable, tmp->foo,
strlen(tmp
->foo)));
}

别忘记了释放空间——其内部元素的分配都是malloc机制的。

/* finitialze the hash table */
hash_table_finit(
&mytable);

下载代码 hashtable

posted @ 2011-04-07 13:50  westfly  阅读(667)  评论(0编辑  收藏  举报