zoukankan      html  css  js  c++  java
  • hashmap

    hashmap.h

    #ifndef foohashmaphfoo
    #define foohashmaphfoo
    
    /* $Id: hashmap.h 90 2004-07-17 14:12:30Z lennart $ */
    
    /***
      This file is part of polypaudio.
     
      polypaudio is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
      by the Free Software Foundation; either version 2 of the License,
      or (at your option) any later version.
     
      polypaudio is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      General Public License for more details.
     
      You should have received a copy of the GNU General Public License
      along with polypaudio; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      USA.
    ***/
    
    struct pa_hashmap;
    
    struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b));
    void pa_hashmap_free(struct pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata);
    
    int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value);
    void* pa_hashmap_get(struct pa_hashmap *h, const void *key);
    
    int pa_hashmap_remove(struct pa_hashmap *h, const void *key);
    
    unsigned pa_hashmap_ncontents(struct pa_hashmap *h);
    
    #endif

    hashmap.c

    /* $Id: hashmap.c 90 2004-07-17 14:12:30Z lennart $ */
    
    /***
      This file is part of polypaudio.
     
      polypaudio is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
      by the Free Software Foundation; either version 2 of the License,
      or (at your option) any later version.
     
      polypaudio is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      General Public License for more details.
     
      You should have received a copy of the GNU General Public License
      along with polypaudio; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      USA.
    ***/
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    
    #include "hashmap.h"
    #include "idxset.h"
    
    struct hashmap_entry {
        //bucket_next, bucket_previous用于data数组,连接相邻的两个元素;next,previous用于first_entry的链表中两个相邻元素的连接
        struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous;
        //hash 值
        unsigned hash;
        //key
        const void *key;
        //key 对应的data
       void *value;
    };
    
    struct pa_hashmap {
         //data数组的大小,固定为1023
         unsigned size;
        //index是由key进行hash后,对1023取余得到的
        //将对应的 hashmap_entry *存入data[index]指定的链表
        struct hashmap_entry **data;
        //对所有的元素进行存入链表中
       struct hashmap_entry *first_entry;
        
        //hashmap_entry元素的个数
        unsigned n_entries;
        //对key取hash的函数
       unsigned (*hash_func) (const void *p);
        //key的比较函数
       int (*compare_func) (const void*a, const void*b);
    };
    
    //初始化pa_hashmap
    struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) {
        struct pa_hashmap *h;
        h = malloc(sizeof(struct pa_hashmap));
        assert(h);
        //data分配一个1023大小的数组,每个元素是hashmap_entry*
        h->data = malloc(sizeof(struct hashmap_entry*)*(h->size = 1023));
        assert(h->data);
        memset(h->data, 0, sizeof(struct hashmap_entry*)*(h->size = 1023));
        h->first_entry = NULL;
        h->n_entries = 0;
        h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func;
        h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func;
        return h;
    }
    
    //将h中的e删除
    //从两个双向链表中删除;删除元素本身;个数减1
    static void remove(struct pa_hashmap *h, struct hashmap_entry *e) {
        assert(e);
       
        //e->next为非空,表示不是链表的最后一个元素
        if (e->next)
            e->next->previous = e->previous;
        //e->previous为非空,表示不是链表的第一个元素
        if (e->previous)
            e->previous->next = e->next;
        else
            h->first_entry = e->next;
    
        //e->bucket_next为非空,表示不是data[index]指向的链表的最后一个元素
        if (e->bucket_next)
            e->bucket_next->bucket_previous = e->bucket_previous;
        //e->bucket_previous为非空,表示不是data[index]指向的链表的第一个元素
        if (e->bucket_previous)
            e->bucket_previous->bucket_next = e->bucket_next;
        else
            h->data[e->hash] = e->bucket_next;
    
        free(e);
        //个数减1
        h->n_entries--;
    }
    
    //释放h
    //h->first_entry的链表指向所有的元素,对每个元素进行删除;释放data数组;释放h
    void pa_hashmap_free(struct pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) {
        assert(h);
    
        while (h->first_entry) {
            if (free_func)
                free_func(h->first_entry->value, userdata);
            remove(h, h->first_entry);
        }
        
        free(h->data);
        free(h);
    }
    
    //在h中取得hash (实际上也是由key得到的)和key指向的hashmap_entry*
    //用key得到hashmap_entry*
    static struct hashmap_entry *get(struct pa_hashmap *h, unsigned hash, const void *key) {
        struct hashmap_entry *e;
        
        //在h->data[hash]的链表中,遍历查找key元素的hashmap_entry*
        for (e = h->data[hash]; e; e = e->bucket_next)
            if (h->compare_func(e->key, key) == 0)
                return e;
    
        return NULL;
    }
    
    //插入key和value到h中
    //检查key是否重复,重复返回-1;不重复,插入到h->first_entry和h->data[hash]中链表的开头;数目加1
    int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value) {
        struct hashmap_entry *e;
        unsigned hash;
        assert(h && key);
        //计算hash
        hash = h->hash_func(key) % h->size;
        //用hash和key获取hashmap_entry * 
        if ((e = get(h, hash, key)))
            return -1; //如果存在,返回-1表示插入重复key
        
        e = malloc(sizeof(struct hashmap_entry));
        assert(e);
        
        e->hash = hash;
        e->key = key;
        e->value = value;
        
        //插入到h->first_entry指向的双向链表的开头
        e->previous = NULL;
        e->next = h->first_entry;
        if (h->first_entry)
            h->first_entry->previous = e;
        h->first_entry = e;
        
        //插入到h->data[hash]指向的双向链表的开头
        e->bucket_previous = NULL;
        e->bucket_next = h->data[hash];
        if (h->data[hash])
            h->data[hash]->bucket_previous = e;
        h->data[hash] = e;
        
        //数目加1
        h->n_entries ++;
        return 0;
    }
    
    //在h中取得key对应的data
    //有key计算hash;由hash和key取得hashmap_entry *;返回hashmap_entry *中的value
    void* pa_hashmap_get(struct pa_hashmap *h, const void *key) {
        unsigned hash;
        struct hashmap_entry *e;
        assert(h && key);
        //由key计算hash
        hash = h->hash_func(key) % h->size;
        //由key和hash取得hashmap_entry *
        if (!(e = get(h, hash, key)))
            return NULL; //key没有插入到h中
    
        return e->value; //返回key对应的data
    }
    //删除key指定的元素
    int pa_hashmap_remove(struct pa_hashmap *h, const void *key) {
        struct hashmap_entry *e;
        unsigned hash;
        assert(h && key);
        //由key计算hash
        hash = h->hash_func(key) % h->size;
        //由key和hash取得hashmap_entry *
        if (!(e = get(h, hash, key)))
            return 1;
        //删除h中的e元素
        remove(h, e);
        return 0;
    }
    //返回元素的个数
    unsigned pa_hashmap_ncontents(struct pa_hashmap *h) {
        return h->n_entries;
    }
  • 相关阅读:
    朋友面试被问到---静态构造函数
    (设计模式之一)浅析简单工厂模式
    out与ref修饰符
    图解引用类型
    图解值类型
    PHP之路---1---Wamp环境配置--php环境配置
    js遮罩层弹出框
    总结
    PSP记录个人项目耗时情况
    代码复审
  • 原文地址:https://www.cnblogs.com/renhl/p/12953550.html
Copyright © 2011-2022 走看看