C语言hashmap
来源:互联网 发布:达梦数据库下载网盘 编辑:程序博客网 时间:2024/05/17 10:05
前几天在用stl中hash_map的时候,发现char*做为key,在比较的时候是直接==,这很蛋疼,我字符串比较你就给直接==,逗我呢。
但是可以重定义hash和compare函数来达到效果,想了想,弄一个这么难用的hash_map还要自己实现,那我还不如自己写一个得了,于是就有了下面的代码。
通过地址散列和链表冲突来实现。
头文件:
#ifndef _E_MAP_H_#define _E_MAP_H_#include "common.h"#ifdef __cplusplus extern "C" { #endif // 在调用了if_map_delete\if_map_clear之后,这个回调来处理value// 如果是safe状态,那么回调结束后会回收,不是safe状态,key将由你来释放内存// value的必须要你来释放内存typedef void (if_map_valueDeleteCallBack)(void *key, void* value);// 初始化一个map// capacity: -1表示自动扩容,0表示没有大小,put/get任何都会失败// safe: FALSE 表示map不会为key生成一份copy,这样key有可能会被你修改,则会出错;// TRUE 则会为key生成一份copy,这样会导致内存稍微增大,但是key不会被修改// key在移除的时候会始终删除void* if_map_new(int capacity, BOOL safe, if_map_valueDeleteCallBack *vdcb);// 放入一个key value// return: 如果之前存在这个key,那么之前的值会返回void* if_map_put(void* map, char* key, void* value);// 得到valuevoid* if_map_get(void* map, char* key);// map的value数量int if_map_size(void* map);// 得到所有values// 配合size使用void** if_map_values(void* map);// 是否存在BOOL if_map_has(void* map, char* key);// 是否包含这个value值,简单的value == valueBOOL if_map_contain(void* map, void* value);// 通过key,移出key-valuevoid* if_map_remove(void* map, char* key);// 通过value,移出key-valuevoid* if_map_removeValue(void* map, void* value);// 移出所有key-valuevoid if_map_clear(void* map);// 释放map内存void if_map_delete(void* map);#ifdef __cplusplus } #endif #endif
#include "map.h"#include "util.h"// key采用取留余数法// 解决冲突采用链地址法typedef struct if_pair_struct {char *key;void *value;} ifpair;typedef struct if_node_struct {ifpair *pair; struct if_node_struct *next;} ifnode;typedef struct if_map_struct { BOOL safe; int capacity; int size; BOOL autoExpand; if_map_valueDeleteCallBack *valueCallback; // node集合 ifnode **nodes;} ifmap;#define MAP_DEFAULT_SIZE 16#define EXPAND_THRESHOLD_RATE 0.75#define EXPAND_FACTOR 2// hash算法// put性能static int hash(int capacity, char* key) { int h = 1; char ch; while (ch = *key++) { h = 31 * h + ch; } return abs(h % capacity);}// key的比较函数// get性能static BOOL compare(char *k1, char *k2) {return if_str_cmp(k1, k2) == 0;}// 对map进行扩容static void expand(ifmap *map) { int i; register int preCapacity = map->capacity; // 保存之前的node数组 register ifnode **preNodes = map->nodes; // 扩容 map->capacity = map->capacity * EXPAND_FACTOR; map->nodes = (ifnode**) malloc (sizeof(ifnode*) * map->capacity); memset(map->nodes, 0, sizeof(ifnode*) * map->capacity); // 移动node for (i = 0; i < preCapacity; i++) { ifnode *node = preNodes[i]; if (node) { int hsKey = hash(map->capacity, node->pair->key); map->nodes[hsKey] = node; } }free(preNodes);}// 删除pair,只会删除key,不会删除valuestatic void if_map_deletePair(ifpair *pair, BOOL safe, if_map_valueDeleteCallBack *cb) { if (pair) { // 只需要释放keyif (cb) { cb(pair->key, pair->value); }if (pair->key && safe) {free(pair->key);pair->key = 0;} free(pair); }}// 删除pair,只会删除key,不会删除valuestatic void if_map_deleteNode(ifnode *node, BOOL deletePair, BOOL safe, if_map_valueDeleteCallBack *cb) { if (node) { // 只需要释放key if (deletePair && node->pair) { if_map_deletePair(node->pair, safe, cb); } free(node); }}// 在一个map中放入一个node// check: 是否检查是否重复的key值// 检查存在 返回之前的pairstatic ifpair* if_map_putPair(ifmap *map, ifpair *pair, BOOL check) { int hsKey = hash(map->capacity, pair->key); ifnode *hashNode = map->nodes[hsKey]; ifnode **ptr = NULL; if (hashNode) { // 存在node // 检查元素的key值 if (check) { if (compare(pair->key, hashNode->pair->key)) { // 这个存在,那么替换pair ifpair *tmpPair = hashNode->pair; hashNode->pair = pair; return tmpPair; } } // 之前的位置上有node,那么需要循环链式遍历 while (hashNode->next) { hashNode = hashNode->next; } ptr = &(hashNode->next); } else { // 不存在node ptr = &(map->nodes[hsKey]); } { // 构造一个新的node ifnode *node = (ifnode*) malloc (sizeof(ifnode)); // 内存分配失败if (!node) {return NULL;}node->pair = pair; node->next = NULL; *ptr = node; // 大小+1 map->size++; } return NULL;}// remove: 是否在得到的时候移出static ifpair* if_map_getPair(ifmap* map, char* key, BOOL remove) { int hs = hash(map->capacity, key); ifnode *topNode = map->nodes[hs]; ifnode *node = topNode; ifnode *preNode = NULL; ifpair *pair = NULL; while (node) { if (compare(key, node->pair->key)) { // 找到 pair = node->pair; break; } else { // 没有找到 preNode = node; node = node->next; } } if (pair && remove) { if (node == topNode) { // 位于散列表 map->nodes[hs] = topNode->next; } else { // 位于链表 preNode->next = node->next;if_map_deleteNode(node, FALSE, map->safe, NULL); } map->size--; } return pair;}// remove: 是否在得到的时候移出static ifpair* if_map_getPairValue(ifmap* map, void* value, BOOL remove) { int i;ifpair *pair = NULL; for (i = 0; i < map->capacity; i++) { ifnode *topNode = map->nodes[i]; ifnode *node = topNode; ifnode *preNode = NULL; while (node) { if (value == node->pair->value) { pair = node->pair; break; } else { // 没有找到 preNode = node; node = node->next; } } if (pair && remove) { if (node == topNode) { // 位于散列表 map->nodes[i] = topNode->next; } else { // 位于链表 preNode->next = node->next;if_map_deleteNode(node, FALSE, map->safe, NULL); } map->size--; }if (pair) {break;} } return pair;}// 初始化一个map// size: -1表示自动扩容,0表示没有大小,put/get任何都会失败// safe: FALSE 表示map不会为key生成一份copy,这样key有可能会被你修改,则会出错; TRUE 则会为key生成一份copy,这样会导致内存稍微增大,但是key不会被修改void* if_map_new(int capacity, BOOL safe, if_map_valueDeleteCallBack *vdcb) { ifmap *map = (ifmap*) malloc (sizeof(ifmap));memset(map, 0, sizeof(ifmap)); if (capacity < 0) { // 自动扩容 map->autoExpand = TRUE; map->size = 0; map->capacity = MAP_DEFAULT_SIZE; } else { map->autoExpand = FALSE; map->size = 0; map->capacity = capacity; }map->valueCallback = vdcb; map->safe = safe; // 分配节点指针空间 map->nodes = (ifnode**) malloc (sizeof(ifnode*) * map->capacity); memset(map->nodes, 0, sizeof(ifnode*) * map->capacity);return map;}// 放入一个key value// return: 如果之前存在这个key,那么之前的值会返回void* if_map_put(void* m, char* key, void* value) { ifmap *map = (ifmap*) m; if (if_str_len(key) == 0) { return NULL; } // 判断是否超过限制 if (!map->autoExpand && map->size >= map->capacity) { return NULL; } // 判断是否需要扩容 if (map->autoExpand && map->size >= (map->capacity * EXPAND_THRESHOLD_RATE)) { // 开始扩容 expand(map); } { // 构造一个pair void *ret = NULL; ifpair *pair = (ifpair*) malloc (sizeof(ifpair)); // 为了安全 if (map->safe) { key = if_str_clone(key); } pair->key = key; pair->value = value; pair = if_map_putPair(map, pair, TRUE); // 之前存在相同的key的pair if (pair) { ret = pair->value; if_map_deletePair(pair, map->safe, NULL); } return ret; }}// 得到valuevoid* if_map_get(void* m, char* key) { if (if_str_len(key) == 0 || !m) { return NULL; } else { ifmap *map = (ifmap*) m; void *ret = NULL; ifpair *pair = if_map_getPair(map, key, FALSE); if (pair) { ret = pair->value; } return ret; }}// map的value数量int if_map_size(void* m) { if (!m) { return -1; } else { ifmap *map = (ifmap*)m; return map->size; }}// 得到所有values// 使用完请释放内存void** if_map_values(void* m) { if (!m) { return NULL; } else { int i; ifmap *map = (ifmap*)m; void **ret = (void**) malloc (sizeof(void*) * map->size);int valuePtr = 0; for (i = 0; i < map->capacity; i++) { ifnode *node = map->nodes[i]; while (node) { ret[valuePtr++] = node->pair->value; node = node->next; } } return ret; }}// 是否存在BOOL if_map_has(void* m, char* key) { if (!m) { return FALSE; } else { int i; ifmap *map = (ifmap*)m;ifnode *node = map->nodes[hash(map->capacity, key)]; while (node) { if (compare(key, node->pair->key)) { return TRUE; } node = node->next; } return FALSE; }}// 是否包含这个value值,简单的value == valueBOOL if_map_contain(void* m, void* value) { if (!m) { return FALSE; } else { int i; ifmap *map = (ifmap*)m; for (i = 0; i < map->capacity; i++) { ifnode *node = map->nodes[i]; while (node) { if (value == node->pair->value) { return TRUE; } node = node->next; } } return FALSE; }}// 通过key,移出key-valuevoid* if_map_remove(void* m, char* key) { if (if_str_len(key) == 0 || !m) { return NULL; } else { ifmap *map = (ifmap*) m; void *ret = NULL; ifpair *pair = if_map_getPair(map, key, TRUE); if (pair) { ret = pair->value; if_map_deletePair(pair, map->safe, NULL); } return ret; }}// 通过value,移出key-value// 通过遍历查找,没有用value来索引void* if_map_removeValue(void* m, void* value) { if (!m) { return NULL; } else { ifmap *map = (ifmap*) m; void *ret = NULL; ifpair *pair = if_map_getPairValue(map, value, TRUE);if (pair) {ret = pair->value;} return ret; }}// 移出所有void if_map_clear(void* m) { if (!m) { return; } else {int i; ifmap *map = (ifmap*) m;// 遍历node for (i = 0; i < map->capacity; i++) { ifnode *node = map->nodes[i]; while (node) {ifnode *nextNode = node->next; if_map_deleteNode(node, TRUE, map->safe, map->valueCallback);node = nextNode; } }memset(map->nodes, 0, sizeof(ifnode*) * map->capacity);map->size = 0; return; }}// 释放一个map的内存void if_map_delete(void* m) { if (!m) { return; } else {int i; ifmap *map = (ifmap*) m; // 遍历node for (i = 0; i < map->capacity; i++) { ifnode *node = map->nodes[i]; while (node) { ifnode *nextNode = node->next; if_map_deleteNode(node, TRUE, map->safe, map->valueCallback);node = nextNode; } } free(map->nodes); free(map); }}
阅读全文
0 0
- hashmap C语言实现
- C语言实现HashMap
- c语言 ---- HashMap实现
- C语言hashmap
- 一个简单的HashMap C语言实现
- 一个简单的HashMap C语言实现
- c语言下的hashmap实现
- c语言实现通用数据结构:通用映射(HashMap)
- C语言实现hashmap,安卓系统AOSP源码
- hashmap c
- Q 语言 -- HashMap
- Java语言-HashMap-HashMap的工作原理
- c语言实现通用数据结构(五):通用映射(HashMap)
- c语言实现通用数据结构(五):通用映射(HashMap)
- [C++]HashMap实现STL map
- c.hashMap源码解析(1.7)
- 【Java语言学习】之HashMap遍历方法
- C语言
- Mac下Sqoop安装与使用
- 用textView实现放大首个字符
- 第七章:复用类
- 学习Python以及其他知识时自己出现的问题
- 产品自主组装树形结构CSS实现(手机、电脑自适应)
- C语言hashmap
- Arctic Network POJ
- 三种主流芯片架构
- 51nod_1256 乘法逆元
- Mqtt精髓系列之连接建立过程
- 莱布尼兹乘积微分公式证明纠错
- 测试Mysql 事务隔离级别
- 数字图像处理matlab版第十二章
- HDOJ1061 Rightmost Digit