uthash:C语言中的高效哈希表实现指南

uthash:C语言中的高效哈希表实现指南

uthash C macros for hash tables and more uthash 项目地址: https://gitcode.com/gh_mirrors/ut/uthash

什么是uthash?

uthash是一个用C语言实现的哈希表库,它通过一组宏定义提供了完整的哈希表功能。与传统的库不同,uthash仅由一个头文件uthash.h组成,无需编译链接,只需包含这个头文件即可使用。

为什么选择uthash?

  1. 轻量级:仅约1000行C代码
  2. 高效:添加、查找和删除操作通常为常数时间复杂度
  3. 易用:通过宏定义提供简洁的API
  4. 跨平台:支持Linux、Windows、Solaris等多种平台
  5. 灵活:支持任意类型的键和结构体

基本使用

1. 定义可哈希的结构体

#include "uthash.h"

struct my_struct {
    int id;                    // 键字段
    char name[10];
    UT_hash_handle hh;         // 必须包含的哈希处理字段
};

UT_hash_handle字段是uthash内部使用的,用于维护哈希表结构。虽然可以任意命名,但命名为hh可以使用更方便的宏。

2. 声明哈希表

struct my_struct *users = NULL;  // 必须初始化为NULL

3. 添加元素

void add_user(int user_id, char *name) {
    struct my_struct *s;
    
    // 检查键是否已存在
    HASH_FIND_INT(users, &user_id, s);
    if (s == NULL) {
        s = malloc(sizeof *s);
        s->id = user_id;
        HASH_ADD_INT(users, id, s);
    }
    strcpy(s->name, name);
}

注意:一旦将结构体添加到哈希表中,就不应修改其键值。

4. 查找元素

struct my_struct *find_user(int user_id) {
    struct my_struct *s;
    HASH_FIND_INT(users, &user_id, s);
    return s;
}

5. 删除元素

void delete_user(struct my_struct *user) {
    HASH_DEL(users, user);
    free(user);  // uthash不会自动释放内存
}

6. 遍历哈希表

void print_users() {
    struct my_struct *s, *tmp;
    
    HASH_ITER(hh, users, s, tmp) {
        printf("user id %d: name %s\n", s->id, s->name);
        // 可以安全地在这里删除和释放s
    }
}

7. 排序

int name_sort(struct my_struct *a, struct my_struct *b) {
    return strcmp(a->name, b->name);
}

void sort_by_name() {
    HASH_SORT(users, name_sort);
}

高级特性

多字段键

uthash支持使用多个字段作为复合键:

struct my_struct {
    int id;
    char name[10];
    UT_hash_handle hh;
};

// 添加元素时使用两个字段作为键
HASH_ADD(hh, users, id, sizeof(int)+sizeof(name), s);

内存考虑

  • 每个元素的内存开销:
    • 32位系统:约32字节
    • 64位系统:约56字节
  • 可以使用HASH_OVERHEAD宏获取哈希表的总开销

线程安全

uthash本身不是线程安全的。在多线程环境中使用时,需要自行添加适当的同步机制。

性能建议

  1. 选择合适的哈希函数对性能至关重要
  2. 对于已知的键类型,使用对应的便捷宏(如HASH_ADD_INT)可以获得更好的性能
  3. 批量删除时使用HASH_CLEAR比逐个删除更高效

常见问题

Q:为什么uthash不检查键的唯一性?

A:为了性能考虑。检查唯一性需要额外的查找操作,对于已知键唯一的场景可以节省这部分开销。

Q:删除元素时哈希表指针会变化吗?

A:如果删除的是哈希表的第一个元素,表头指针会改变。

Q:如何传递哈希表到函数中?

A:需要传递哈希表指针的地址:

void modify_hash(struct my_struct **hash) {
    // 使用*hash访问哈希表
    HASH_ADD_INT(*hash, id, new_item);
}

总结

uthash为C语言程序提供了简单高效的哈希表实现。它的宏定义接口使得使用非常方便,同时保持了良好的性能。无论是小型项目还是大型系统,uthash都是一个值得考虑的哈希表解决方案。

通过合理使用uthash提供的各种宏,可以轻松实现添加、查找、删除、遍历和排序等常见哈希表操作,大大简化了C语言中处理键值对数据的复杂度。

uthash C macros for hash tables and more uthash 项目地址: https://gitcode.com/gh_mirrors/ut/uthash

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

符汝姿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值