一个简单的HashMap C语言实现
Posted 车斗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个简单的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.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 * h + * 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;
}
* 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 * h + * 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)看我下一篇文章!
以上是关于一个简单的HashMap C语言实现的主要内容,如果未能解决你的问题,请参考以下文章