zoukankan      html  css  js  c++  java
  • 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("===========
    ");
    24     HASH_ITER(hh, bucket, cur, tmp) {
    25         printf("%d %s
    ", 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 }
  • 相关阅读:
    Python3 CGI编程实现教程
    SSL密钥协商过程分析
    浏览器同源策略理解
    Python3+selenium 报错处理:“selenium.common.exceptions.NoAlertPresentException: Message: No alert is active”
    Python3 try-except、raise和assert解析
    计算机视觉常见技术(待理解)
    中国大学MOOC-陈越、何钦铭-数据结构-2017春
    Coursera机器学习+deeplearning.ai+斯坦福CS231n
    总结一些机器视觉库
    git rebase 多分支操作
  • 原文地址:https://www.cnblogs.com/hemeiwolong/p/15245054.html
Copyright © 2011-2022 走看看