一个简单的HashMap C语言实现

一个简单的HashMap C语言实现

cheungmine 

用C语言实现一个简单实用的hashmap,具有一定的实际意义。尤其我们不想使用STL里面的map<...>类的时候。我实现的这个hashmap,用来做key---value的映射,key必须是有效的字符串,value是调用者分配的任意类型的数据。这个hashmap适合在一些简单的场合下,消耗极少的资源。

首先定义头文件如下:

 

/*
 * hashmap.h
 *        Generic hash map: key(string)-value(any type).
 *        cheungmine 
 *      Sep. 22, 2007.  All rights reserved.
 
*/
#ifndef HASHMAP_H_INCLUDED
#define  HASHMAP_H_INCLUDED

#include 
" unistd.h "

/*  You should always use 1024  */
#define      HASHMAP_SIZE    1024

/*  Opaque struct pointer to _hash_map_t  */
typedef 
struct     _hash_map_t *         hash_map;

typedef 
void ( * pfcb_hmap_value_free)( void *  value);

/*  An example of free value function implemented by caller:
void my_hmap_free_value(void* pv)
{
    free(pv);
}
*/


/*  Create before use. eg:
 * hash_map  hm;
 * hmap_create (&hm, HASHMAP_SIZE);
 * assert (hm);     // out of memory if hm==NULL 
 * void* mydata=malloc(n);
 * hmap_insert(hm, "shanghai", -1, mydata);
   ...
 * hmap_destroy(hm, my_hmap_free_value);
 
*/
extern   void  
hmap_create(hash_map 
* hmap,  int  size);

/*  Destroy after use  */
extern   void  
hmap_destroy(hash_map hmap, pfcb_hmap_value_free);

/*  Insert a key-value into hash map. value is a pointer to callee-allocated memory  */
extern   void  
hmap_insert(hash_map hmap, 
const   char *  key,  int  key_len /*  -1 for strlen to be called  */ void *  value);

/*  Search a hash map for value of given key string  */
extern   void *   
hmap_search(hash_map hmap, 
const   char    * key);


#endif   /* HASHMAP_H_INCLUDED */

 

实现文件如下:

 

/*
 * hashmap.c
 *        Generic hashmap implementation. 
 *      a map for pair of key-value. key must be a null-end string, value is any type of data.
 *        cheungmine 
 *      Sep. 22, 2007.  All rights reserved.
 
*/

#include 
" hashmap.h "
#include 
" list.h "

typedef 
struct  _hash_map_t
{
    size_t            size;
    listnode_t
**     key;
    listnode_t
**     value;
}hash_map_t;

/*  Hash a string, return a hash key  */
static   ulong   hash_string( const   char    * s,  int  len)
{
    
ulong  h  =   0 ;
    
int    i  =   0 ;
    assert (s);
    
if  (len  <   0 )
        len 
=  (s ?  ( int )strlen(s):  0 );
    
while (i ++   <  len) { h  =   17 * +   * s ++ ; }
    
return  h;    
}

static   void  _free_map_key(listnode_t *  node)
{
    listnode_t    
* old;
    
while (node)
    {        
        old 
=  node;
        node 
=  node -> next;
        
        free(old
-> data);        
        free (old);
    }
}

static   void  _free_map_value(listnode_t *  node, pfcb_hmap_value_free pfunc)
{
    listnode_t    
* old;
    
while (node)
    {        
        old 
=  node;
        node 
=  node -> next;
        
        
if  (pfunc)
            (
* pfunc)(old -> data);        
        free (old);
    }
}

/* =============================================================================
                            Public Functions
=============================================================================
*/
/*  Create before use  */
void  
hmap_create(hash_map 
* hmap,  int  size)
{
    (
* hmap)  =  (hash_map_t * ) malloc( sizeof (hash_map_t));
    (
* hmap) -> size  =  size;
    (
* hmap) -> key  =  (listnode_t ** ) calloc(size,  sizeof (listnode_t * ));
    (
* hmap) -> value  =  (listnode_t ** ) calloc(size,  sizeof (listnode_t * ));
}

/*  Destroy after use  */
extern   void  
hmap_destroy(hash_map hmap, pfcb_hmap_value_free pfunc)
{
    size_t i;
    
for (i = 0 ; i < hmap -> size; i ++ ){
        _free_map_key(hmap
-> key[i]);
        _free_map_value(hmap
-> value[i], pfunc);
    }
    
    free(hmap
-> key);
    free(hmap
-> value);
    free(hmap);
}


/*  Insert a key-value into hash map. value is a pointer to callee-allocated memory  */
void  
hmap_insert(hash_map hmap, 
const   char *  key,  int  key_len,  void *  value)
{
    listnode_t    
* node_key,  * node_val;
    
ulong         h;
    
char          * s;
    assert (key);

    
if  (key_len < 0 ) key_len  =  ( int ) strlen (key);
    s 
=  ( char * ) malloc (key_len + 1 );
    assert(s);

#pragma  warning(push)    /* C4996 */
#pragma  warning( disable : 4996 )
    strncpy (s, key, key_len);
#pragma  warning(pop)    /* C4996 */
    s[key_len] 
=   0 ;
    
    node_key 
=  list_node_create ( ( void * )s );
    node_val 
=  list_node_create ( value );
    assert(node_key 
&&  node_val);

    h 
=  hash_string (s, key_len)  %  hmap -> size;

    node_key
-> next  =  hmap -> key[h];
    hmap
-> key[h]  =  node_key;
    
    node_val
-> next  =  hmap -> value[h];
    hmap
-> value[h]  =  node_val;
}

/*  Search a hash map for value of given key string  */
void *   
hmap_search(hash_map hmap, 
const   char   * key)
{
    
ulong         h     =  hash_string (key,  - 1 %  hmap -> size;
    listnode_t  
* pk  =  hmap -> key[h];
    listnode_t  
* pv  =  hmap -> value[h];

    
while  (pk)
    {
        
if  (strcmp(key, pk -> str)  ==   0 )
            
return  pv -> data;        
        pk 
=  pk -> next;
        pv 
=  pv -> next;
    }

    
return  NULL;
}

 

好了,其中用到的其他文件(unistd.h,list.h,list.c)看我下一篇文章!

C语言实现一个简单的单向链表list

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
C语言的哈希表(hashmap)可以通过数组和链表的结合实现。 首先,我们需要定义一个结构体来表示哈希表的节点,包含一个键和一个值。例如: ``` typedef struct Node { int key; int value; struct Node* next; } Node; ``` 接下来,我们需要定义一个数组作为哈希表的桶(bucket),桶的数量通常选择为一个质数,以减少冲突的概率。例如: ``` #define BUCKET_SIZE 100 // 创建一个指向Node指针数组的指针 Node** hashMap = NULL; // 初始化哈希表 void init() { hashMap = (Node**)malloc(BUCKET_SIZE * sizeof(Node*)); for (int i = 0; i < BUCKET_SIZE; i++) { hashMap[i] = NULL; } } ``` 为了实现哈希函数,我们可以使用取余操作符(%),将键映射到桶的索引上。例如,我们可以使用键的整数值除以桶的大小,并取余运算来计算索引: ``` int hash(int key) { return key % BUCKET_SIZE; } ``` 接下来,我们可以实现插入和查找操作。 插入操作首先需要先检查键是否存在于哈希表中,如果存在,则更新值;如果不存在,则创建新节点,并将节点添加到对应桶的链表上。例如: ``` void insert(int key, int value) { int index = hash(key); Node* node = hashMap[index]; // 查找节点 while (node != NULL) { if (node->key == key) { node->value = value; // 更新值 return; } node = node->next; } // 创建新节点 node = (Node*)malloc(sizeof(Node)); node->key = key; node->value = value; node->next = hashMap[index]; hashMap[index] = node; } ``` 查找操作首先计算键的哈希值,并遍历对应桶上的链表,直到找到与给定键相等的节点或链表末尾。例如: ``` int get(int key) { int index = hash(key); Node* node = hashMap[index]; // 查找节点 while (node != NULL) { if (node->key == key) { return node->value; // 返回值 } node = node->next; } return -1; // 没有找到 } ``` 此外,我们还可以实现删除操作和释放内存的函数,确定哈希表是否需要动态调整大小等。 以上就是C语言实现哈希表的简单示例。哈希表在C语言中非常常用,可以用于解决快速查找和插入的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

车斗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值