69,369
社区成员
发帖
与我相关
我的任务
分享
/*
* hashMap.c
* 通用散列表的实现
* 将键-值(key-value)对存入散列表,键(key)必须为空值结束的字符串,值(value)可以为任意类型的数据
*/
#include "hashMap.h"
#include "list.c"
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->nodeData.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->nodeData.data);
free(old);
}
}
/*=============================================================================
公用函数
=============================================================================*/
/* 使用前创建 */
void hashMapCreate(HashMap *hashMap, int size) {
(*hashMap) = (hash_map_t*) malloc(sizeof (hash_map_t));
(*hashMap)->size = size;
(*hashMap)->key = (listnode_t**) calloc(size, sizeof (listnode_t*));
(*hashMap)->value = (listnode_t**) calloc(size, sizeof (listnode_t*));
}
/* 用完后清除 */
extern void hashMapDestroy(HashMap hashMap, pfcb_hmap_value_free pfunc) {
/*请实现该函数*/
}
/* 向散列表插入键-值对(key-value),值为调用程序分配的内存指针 */
void hashMapInsert(HashMap hashMap, const char* key, int key_len, void* value) {
/*请实现该函数*/
//hashMap->size=key_len;
// hashMap.key=key;
// hashMap.value=value;
}
/* 用指定的字符串(键)在散列表中查找对应的值 */
void* hashMapSearch(HashMap hashMap, const char *key) {
/*请实现该函数*/
//hashMap.key
}
/*
* File: hashMap.h
* Author: zhangtaihong
*
* Created on 2013年8月7日, 下午12:24
*/
#ifndef HASHMAP_H
#define HASHMAP_H
#ifdef __cplusplus
extern "C" {
#endif
#include "unistd.h"
/* 静态散列表主桶的数量 */
#define HASHMAP_SIZE 1024
/* 指向_hash_map_t结构的不透明指针,隐藏_hash_map_t的实现细节 */
typedef struct _hash_map_t* HashMap;
typedef void(*pfcb_hmap_value_free)(void* value);
/* 调用程序实现的清除值函数的例子
void my_hmap_free_value(void* pv)
{
free(pv);
}*/
/* 使用前先创建,如:
* HashMap hashMap;
* hashMapCreate(&hashMap, HASHMAP_SIZE);
* assert (hashMap); //如果hashMap==NULL,说明内存不足
* void* mydata=malloc(n);
* hashMapInsert(hm, "shanghai", -1, mydata);
...
* 程序结束前清除散列表
* hashMapDestroy(hashMap, my_hmap_free_value);
*/
extern void hashMapCreate(HashMap *hashMap, int size);
/* 清除散列表 */
extern void hashMapDestroy(HashMap hashMap, pfcb_hmap_value_free pfunc);
/* 向散列表插入键-值对(key-value),值为调用程序分配的内存指针 */
extern void hashMapInsert(HashMap hashMap, const char* key, int key_len/* -1 使用strlen函数 */, void* value);
/* 用指定的可以字符串在散列表中查找键对应的值 */
extern void* hashMapSearch(HashMap hashMap, const char *key);
#ifdef __cplusplus
}
#endif
#endif /* HASHMAP_H */
/*
* File: list.h
* Author: zhangtaihong
* 通用顺序链表及节点结构 -- 可以存储任意类型的数据
* Created on 2013年8月7日, 下午12:28
*/
#ifndef LIST_H
#define LIST_H
#ifdef __cplusplus
extern "C" {
#endif
#include "unistd.h"
struct _listnode_t {
struct _listnode_t *next;
union {
void* data;
struct _list_t *list;
const char *str;
long key;
}nodeData;
};
typedef struct _listnode_t listnode_t;
struct _list_t {
size_t size; /* 节点数量 */
listnode_t *head; /*链表头结点指针*/
listnode_t *tail; /*链表尾结点指针*/
};
typedef struct _list_t list_t;
/* list_destroy()要调用的回调函数的声明, 若为NULL,表示不用回调函数 */
typedef void(*pfcb_list_node_free)(listnode_t* node);
/* 被调用程序实现的节点数据清理函数的例子
void myListNodeFree(listnode_t *node)
{
free(node->nodeData.data);
}*/
/* 向链表添加一个节点 */
extern void listAppendNode(list_t *in_list, listnode_t *in_node);
/* 删除链表的第一个节点,返回新的链表 */
extern listnode_t* listRemoveHead(list_t *in_list);
/* 删除链表中的所有节点,但链表本身依然保留 */
extern void listRemoveAll(list_t *in_list, pfcb_list_node_free pfunc /* NULL for no use or a key node */);
/* 返回链表的一个拷贝 */
extern list_t* listCopy(list_t in_list);
/* 合并两个链表,将second合并到first,不清除second */
extern void list_concat(list_t *first, list_t *second);
/* 创建一个新节点,不为输入的node_data分配内存 */
extern listnode_t* listNodeCreate(void* node_data);
/* 创建一个新节点,整型键值 */
extern listnode_t* listKeyCreate(long node_key);
/* 在队内存创建一个空链表 */
extern list_t* listCreate();
/* 从对内存中清除一个链表
* 被调用程序负责清理节点数据,即该函数会调用节点清理函数(pfunc)
*/
extern void listDestroy(list_t *in_list, pfcb_list_node_free pfunc /* NULL for no use or a key node */);
/* 获取链表中节点的个数 */
extern size_t listSize(const list_t* in_list);
/* 按索引下标获取节点,索引下标从0开始,下标0的节点为头节点 */
extern listnode_t* listNodeAt(const list_t* in_list, int index);
#ifdef __cplusplus
}
#endif
#endif /* LIST_H */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
/* ------------------结构体定义------------------ */
typedef struct _hashBucket_t {
char* key;
size_t key_len;
char* data;
size_t data_len;
struct _hashBucket_t *next;
} hashBucket_t;
typedef struct _hashMap_t {
size_t hash_bits;
size_t bucket_num;
hashBucket_t bucket[0];
} hashMap_t;
/* -----------------hashmap API ------------------ */
/* count: 预计有多少条数据 */
hashMap_t* hashMapCreate(unsigned long count);
void hashMapDestroy(hashMap_t* map);
void hashMapInsert(hashMap_t* map, void* key, size_t key_len, void* data, size_t data_len);
int hashMapSearch(hashMap_t* map, void* key, size_t key_len, void** data, size_t* data_len);
/* ------------------demo------------------------ */
int main(void)
{
hashMap_t* map = NULL;
char* data = NULL;
size_t data_len = 0;
int ret;
map = hashMapCreate(1000);
hashMapInsert(map, "1+1=", 4, "2", 1);
hashMapInsert(map, "1+2=", 4, "3", 1);
hashMapInsert(map, "1+3=", 4, "4", 1);
hashMapInsert(map, "1+4=", 4, "5", 1);
hashMapInsert(map, "1+5=", 4, "6", 1);
hashMapInsert(map, "1+6=", 4, "7", 1);
hashMapInsert(map, "1+7=", 4, "8", 1);
hashMapInsert(map, "1+8=", 4, "9", 1);
hashMapInsert(map, "Hello", -1, "World", -1);
ret = hashMapSearch(map, "Hello", -1, (void**)&data, &data_len);
if (ret == 1) {
printf("%s(len=%zx)\n", data, data_len);
}
else {
printf("not found\n");
}
hashMapDestroy(map);
}
hashMap_t* hashMapCreate(unsigned long count)
{
int i = 0;
size_t bucket_num = 1;
size_t hash_bits = 0;
hashMap_t* map = NULL;
while (1) {
bucket_num *= 2;
hash_bits++;
if (bucket_num >= count) {
break;
}
}
map = (hashMap_t*)calloc(1, sizeof(hashMap_t) + \
sizeof(hashBucket_t) * bucket_num);
map->bucket_num = bucket_num;
map->hash_bits = hash_bits;
return map;
}
void hashMapDestroy(hashMap_t* map)
{
int i;
hashBucket_t* bucket;
hashBucket_t* tmp;
for (i = 0; i < map->bucket_num; i++) {
bucket = &map->bucket[i];
if (bucket->key_len == 0) {
continue;
}
free(bucket->data);
free(bucket->key);
bucket = bucket->next;
while (bucket != NULL) {
free(bucket->data);
free(bucket->key);
tmp = bucket;
bucket = bucket->next;
free(tmp);
}
}
free(map);
}
static unsigned long _calcHashValue(hashMap_t* map, void* key, size_t key_len)
{
char* ch = (char*)key;
unsigned long seed = 131UL;
unsigned long hash = 0UL;
for (ch = (char*)key; ch < (char*)key + key_len; ch++) {
hash = hash * seed + (*ch);
}
hash &= (~0UL >> (sizeof(unsigned long) * 8 - map->hash_bits));
return hash;
}
void hashMapInsert(hashMap_t* map, void* key, size_t key_len, void* data, size_t data_len)
{
unsigned long hash = _calcHashValue(map, key, key_len);
hashBucket_t* bucket = &map->bucket[hash];
if (key_len == -1) {
key_len = strlen((char*)key);
}
if (data_len == -1) {
data_len = strlen((char*)data);
}
if (bucket->key_len) {
while (bucket->next != NULL) {
bucket = bucket->next;
}
bucket->next = (hashBucket_t*)calloc(1, sizeof(hashBucket_t));
bucket = bucket->next;
}
bucket->key = (char*)calloc(1, key_len + 1);
memcpy(bucket->key, key, key_len);
bucket->key_len = key_len;
bucket->data = (char*)calloc(1, data_len + 1);
memcpy(bucket->data, data, data_len);
bucket->data_len = data_len;
}
int hashMapSearch(hashMap_t* map, void* key, size_t key_len, void** data, size_t* data_len)
{
unsigned long hash = _calcHashValue(map, key, key_len);
hashBucket_t* bucket = &map->bucket[hash];
if (key_len == -1) {
key_len = strlen((char*)key);
}
while (bucket != NULL) {
if ((key_len == bucket->key_len) && !memcmp(key, bucket->key, key_len)) {
if (data) {
*data = bucket->data;
}
if (data_len) {
*data_len = bucket->data_len;
}
return 1;
}
bucket = bucket->next;
}
return 0;
}