zoukankan      html  css  js  c++  java
  • 一种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

  • 相关阅读:
    以太坊学习笔记
    linux找不到动态链接库
    centos7 firewall指定IP与端口访问
    VMware Fusion 序列号
    mysql pxc无法启动
    vmware workstation许可证密钥
    Gradle上传依赖到私服(nexus)
    Java对象操作工具
    Java获取不到请求的真实IP
    java8+ Lambda表达式基本用法
  • 原文地址:https://www.cnblogs.com/westfly/p/2007839.html
Copyright © 2011-2022 走看看