uthash总结
参考精选博客:https://blog.csdn.net/whatday/article/details/95926766
uthash.h
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: 哈希表2,提供哈希表的常用简化接口
* Create: 2020-06-01
* Version: V1.4
* Contact: 有任何问题或建议,请前往
* http://rnd-isource.huawei.com/bugs/hw-cstl
*/
#ifndef HHASH2_H
#define HHASH2_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "hhash.h"
struct SimpHash;
/* key 为 int, value 为 uintptr_t 的哈希表接口 */
typedef struct SimpHash IntHash;
static inline IntHash *IntHashCreate(void);
static inline void IntHashDestroy(IntHash *ht);
static inline bool IntHashEmpty(const IntHash *ht);
static inline size_t IntHashSize(const IntHash *ht);
/* 增加 k-v 对,已经存在则刷新 v;成功返回 0,内存错误返回 -1 */
static inline int IntHashSet(IntHash *ht, int k, uintptr_t v);
/* 由 k 查 v;出参 exist 可选,指示是否存在 */
static inline uintptr_t IntHashGet(const IntHash *ht, int k, bool *exist);
/* 指定 k 删除 k-v 对 */
static inline void IntHashDel(IntHash *ht, int k);
/* 指定 k 查询是否存在 */
static inline bool IntHashExist(const IntHash *ht, int k);
/* 迭代处理所有节点 k-v */
typedef void (*IntHashIterFunc)(int k, uintptr_t v, void *arg);
static inline void IntHashIterate(const IntHash *ht, IntHashIterFunc fn, void *arg);
/* key 为 str(const char*), value 为 uintptr_t 的哈希表接口 */
typedef struct SimpHash StrHash;
static inline StrHash *StrHashCreate(void);
static inline void StrHashDestroy(StrHash *ht);
static inline bool StrHashEmpty(const StrHash *ht);
static inline size_t StrHashSize(const StrHash *ht);
/* 增加 k-v 对,已经存在则刷新 v;成功返回 0,内存错误返回 -1 */
static inline int StrHashSet(StrHash *ht, const char *k, uintptr_t v);
/* 由 k 查 v;出参 *exist 指示是否存在 */
static inline uintptr_t StrHashGet(const StrHash *ht, const char *k, bool *exist);
/* 指定 k 删除 k-v 对 */
static inline void StrHashDel(StrHash *ht, const char *k);
/* 指定 k 查询是否存在 */
static inline bool StrHashExist(const StrHash *ht, const char *k);
/* 迭代处理所有节点 k-v */
typedef void StrHashIterFunc(const char *k, uintptr_t v, void *arg);
static inline void StrHashIterate(const StrHash *ht, StrHashIterFunc fn, void *arg);
/* IntHash, StrHash 复用相同的节点类型 */
struct SimpHashNode {
struct Node node;
int intk;
const char *strk;
uintptr_t value;
};
static bool IntNodeEqual(const struct Node *a, const struct Node *b)
{
struct SimpHashNode *na = NODE_ENTRY(a, struct SimpHashNode, node);
struct SimpHashNode *nb = NODE_ENTRY(b, struct SimpHashNode, node);
return na->intk == nb->intk;
}
static bool StrNodeEqual(const struct Node *a, const struct Node *b)
{
struct SimpHashNode *na = NODE_ENTRY(a, struct SimpHashNode, node);
struct SimpHashNode *nb = NODE_ENTRY(b, struct SimpHashNode, node);
return strcmp(na->strk, nb->strk) == 0;
}
static size_t IntNodeKey(const struct Node *node, size_t bktSize)
{
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
size_t k = TwIntHash((unsigned int)n->intk);
return k % bktSize;
}
static size_t StrNodeKey(const struct Node *node, size_t bktSize)
{
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
size_t k = BkdrHash(n->strk);
return k % bktSize;
}
static void SimpHashNodeFree(struct Node *node)
{
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
free(n);
}
#define SIMPLE_HASH_INIT_BKT_SIZE 16
/*
* 每个 hash 桶中节点个数平均值上限
* 当节点增多,导致超过这个值时,hash 桶自动扩充一倍
* 如果有内存空间限制,可以增大该值,对应的搜索时间会增加
*/
#define SIMPLE_HASH_NODE_PER_BKT 1
struct SimpHash {
struct HashTable raw;
size_t nodeCnt;
};
static inline IntHash *IntHashCreate(void)
{
struct SimpHash *ht = (struct SimpHash*)malloc(sizeof(struct SimpHash));
if (ht == NULL) {
return NULL;
}
ht->nodeCnt = 0;
int ret = HashInit(&ht->raw, SIMPLE_HASH_INIT_BKT_SIZE, IntNodeEqual, IntNodeKey);
if (ret != 0) {
free(ht);
return NULL;
}
return ht;
}
static inline StrHash *StrHashCreate(void)
{
struct SimpHash *ht = (struct SimpHash*)malloc(sizeof(struct SimpHash));
if (ht == NULL) {
return NULL;
}
ht->nodeCnt = 0;
int ret = HashInit(&ht->raw, SIMPLE_HASH_INIT_BKT_SIZE, StrNodeEqual, StrNodeKey);
if (ret != 0) {
free(ht);
return NULL;
}
return ht;
}
static inline void IntHashDestroy(IntHash *ht)
{
HashDeinit(&ht->raw, SimpHashNodeFree);
free(ht);
}
static inline void StrHashDestroy(StrHash *ht)
{
HashDeinit(&ht->raw, SimpHashNodeFree);
free(ht);
}
static inline bool IntHashEmpty(const IntHash *ht)
{
return ht->nodeCnt == 0;
}
static inline bool StrHashEmpty(const StrHash *ht)
{
return ht->nodeCnt == 0;
}
static inline size_t IntHashSize(const IntHash *ht)
{
return ht->nodeCnt;
}
static inline size_t StrHashSize(const StrHash *ht)
{
return ht->nodeCnt;
}
static inline int IntHashSet(IntHash *ht, int k, uintptr_t v)
{
struct SimpHashNode cmp = { .intk = k };
struct SimpHashNode *n;
struct Node *node = HashFind(&ht->raw, &cmp.node);
if (node != NULL) {
n = NODE_ENTRY(node, struct SimpHashNode, node);
n->value = v;
return 0;
}
n = (struct SimpHashNode*)malloc(sizeof(struct SimpHashNode));
if (n == NULL) {
return -1;
}
n->intk = k;
n->value = v;
HashAdd(&ht->raw, &n->node);
ht->nodeCnt++;
if (ht->nodeCnt > ht->raw.bktSize * SIMPLE_HASH_NODE_PER_BKT) {
(void)HashReset(&ht->raw, ht->raw.bktSize * 2, NULL, NULL);
}
return 0;
}
static inline int StrHashSet(StrHash *ht, const char *k, uintptr_t v)
{
struct SimpHashNode cmp = { .strk = k };
struct SimpHashNode *n;
struct Node *node = HashFind(&ht->raw, &cmp.node);
if (node != NULL) {
n = NODE_ENTRY(node, struct SimpHashNode, node);
n->value = v;
return 0;
}
size_t len = sizeof(struct SimpHashNode) + strlen(k) + 1;
n = (struct SimpHashNode*)malloc(len);
if (n == NULL) {
return -1;
}
(void)strcpy((char*)(n + 1), k);
n->strk = (const char*)(n + 1);
n->value = v;
HashAdd(&ht->raw, &n->node);
ht->nodeCnt++;
if (ht->nodeCnt > ht->raw.bktSize * SIMPLE_HASH_NODE_PER_BKT) {
(void)HashReset(&ht->raw, ht->raw.bktSize * 2, NULL, NULL);
}
return 0;
}
static inline uintptr_t IntHashGet(const IntHash *ht, int k, bool *exist)
{
struct SimpHashNode cmp = { .intk = k };
struct Node *node = HashFind(&ht->raw, &cmp.node);
if (exist != NULL) {
*exist = node != NULL;
}
if (node != NULL) {
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
return n->value;
}
return 0;
}
static inline uintptr_t StrHashGet(const StrHash *ht, const char *k, bool *exist)
{
struct SimpHashNode cmp = { .strk = k };
struct Node *node = HashFind(&ht->raw, &cmp.node);
if (exist != NULL) {
*exist = node != NULL;
}
if (node != NULL) {
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
return n->value;
}
return 0;
}
static inline void IntHashDel(IntHash *ht, int k)
{
struct SimpHashNode cmp = { .intk = k };
struct Node *node = HashFind(&ht->raw, &cmp.node);
if (node == NULL) {
return;
}
HashRemove(node);
ht->nodeCnt--;
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
free(n);
}
static inline void StrHashDel(StrHash *ht, const char *k)
{
struct SimpHashNode cmp = { .strk = k };
struct Node *node = HashFind(&ht->raw, &cmp.node);
if (node == NULL) {
return;
}
HashRemove(node);
ht->nodeCnt--;
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
free(n);
}
static inline bool IntHashExist(const IntHash *ht, int k)
{
struct SimpHashNode cmp = { .intk = k };
struct Node *node = HashFind(&ht->raw, &cmp.node);
return node != NULL;
}
static inline bool StrHashExist(const StrHash *ht, const char *k)
{
struct SimpHashNode cmp = { .strk = k };
struct Node *node = HashFind(&ht->raw, &cmp.node);
return node != NULL;
}
static inline void IntHashIterate(const IntHash *ht, IntHashIterFunc fn, void *arg)
{
for (size_t i = 0; i < ht->raw.bktSize; i++) {
struct Node *node;
LIST_FOR_EACH(node, &ht->raw.bkts[i]) {
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
fn(n->intk, n->value, arg);
}
}
}
static inline void StrHashIterate(const StrHash *ht, StrHashIterFunc fn, void *arg)
{
for (size_t i = 0; i < ht->raw.bktSize; i++) {
struct Node *node;
LIST_FOR_EACH(node, &ht->raw.bkts[i]) {
struct SimpHashNode *n = NODE_ENTRY(node, struct SimpHashNode, node);
fn(n->strk, n->value, arg);
}
}
}
#endif /* HHASH2_H */
字符串数组作为key示例:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <limits.h> 4 #include <string.h> 5 #include "utlist.h" 6 #include "uthash.h" 7 8 #define LEN 10 9 10 typedef struct _node { 11 char key[LEN]; 12 int num; 13 UT_hash_handle hh; 14 } node; 15 16 node *bucket = NULL; 17 18 void Show() 19 { 20 node *cur = NULL; 21 node *tmp = NULL; 22 23 printf("===========\n"); 24 HASH_ITER(hh, bucket, cur, tmp) { 25 printf("%d %s\n", cur->num, cur->key); 26 } 27 } 28 29 int Cmp(node *a, node *b) 30 { 31 return strcmp(a->key, b->key); 32 } 33 34 int Cmp1(node *a, node *b) 35 { 36 return a->num - b->num; 37 } 38 39 int main() 40 { 41 char strs[LEN * LEN] = "o..g..d.r.h.zs.f.h.r.dz.f.r.fh."; 42 char dlip[LEN] = "."; 43 char *token = strtok(strs, dlip); 44 node *cur = NULL; 45 node *tmp = NULL; 46 47 while (token != NULL) { 48 HASH_FIND_STR(bucket, token, tmp); 49 if (tmp) { 50 tmp->num++; 51 } else { 52 tmp = (node *)malloc(sizeof(node)); 53 memset(tmp, 0, sizeof(tmp)); 54 tmp->num = 1; 55 strcpy(tmp->key, token); 56 HASH_ADD_STR(bucket, key, tmp); 57 } 58 59 token = strtok(NULL, dlip); 60 } 61 Show(); 62 63 HASH_SORT(bucket, Cmp); 64 Show(); 65 HASH_SORT(bucket, Cmp1); 66 Show(); 67 68 HASH_ITER(hh, bucket, cur, tmp) { 69 HASH_DEL(bucket, cur); 70 free(cur); 71 } 72 Show(); 73 74 return 0; 75 }

浙公网安备 33010602011771号