C语言哈希表uthash的使用

C语言的标准库中没有哈希表的函数可以使用,但是可以通过第三方头文件uthash.h这个包来实现哈希表的操作。首先,想要使用这个包,可以访问它的github网站 https://github.com/troydhanson/uthash 下载uthash.h文件。

使用说明

在你的程序中,首先需要定义一个结构体

#include "uthash.h"

struct my_struct {
    int id;                    /* key */
    char name[10];
    UT_hash_handle hh;         /* makes this structure hashable */
};

需要注意的是,当你添加一个结构体变量到哈希表中时,这个结构体不会被复制或者移动到其他地址,所以你还是可以在程序的生命周期中安全的指向这个结构体变量的地址。
每一个这样的结构体由一个id(被当作键值使用),一个要储存的变量,和一个UT_hash_handle变量。UT_hash_handle是非常重要的变量,它是这个结构体能够实现哈希表操作的关键。

然后需要定义一个全局的my_struct变量

struct my_struct *users = NULL /* important! initialize to NULL */
添加元素
void add_user(int user_id, char *name) {
    struct my_struct *s;
    HASH_FIND_INT(users, &user_id, s);  /* id already in the hash? */
    if (s == NULL) {
      s = (struct my_struct *)malloc(sizeof *s);
      s->id = user_id;
      HASH_ADD_INT(users, id, s);  /* id: name of key field */
    }
    strcpy(s->name, name);
}

这里通过HASH_FIND_INT首先确定当前id的唯一性,然后再通过HASH_ADD_INT添加元素。如果当前元素已经存在,那么修改它储存的元素值。

查找元素
struct my_struct *find_user(int user_id) {
    struct my_struct *s;

    HASH_FIND_INT(users, &user_id, s);  /* s: output pointer */
    return s;
}
删除元素
void delete_user(struct my_struct *user) {
    HASH_DEL(users, user);  /* user: pointer to deletee */
    free(user);             /* optional; it's up to you! */
}
清空表
void delete_all() {
  struct my_struct *current_user, *tmp;

  HASH_ITER(hh, users, current_user, tmp) {
    HASH_DEL(users, current_user);  /* delete; users advances to next */
    free(current_user);             /* optional- if you want to free  */
  }
}
计算元素个数
unsigned int num_users;
num_users = HASH_COUNT(users);
printf("there are %u users\n", num_users);
遍历打印所有元素
void print_users() {
    struct my_struct *s;

    for (s = users; s != NULL; s = s->hh.next) {
        printf("user id %d: name %s\n", s->id, s->name);
    }
}
排序
  1. 通过id排序
    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);
    }
    
  2. 通过键值排序
    int id_sort(struct my_struct *a, struct my_struct *b) {
        return (a->id - b->id);
    }
    
    void sort_by_id() {
        HASH_SORT(users, id_sort);
    }
    

完整的例子

#include <stdio.h>   /* gets */
#include <stdlib.h>  /* atoi, malloc */
#include <string.h>  /* strcpy */
#include "uthash.h"

struct my_struct {
    int id;                    /* key */
    char name[10];
    UT_hash_handle hh;         /* makes this structure hashable */
};

struct my_struct *users = NULL;

void add_user(int user_id, char *name) {
    struct my_struct *s;

    HASH_FIND_INT(users, &user_id, s);  /* id already in the hash? */
    if (s == NULL) {
      s = (struct my_struct *)malloc(sizeof *s);
      s->id = user_id;
      HASH_ADD_INT(users, id, s);  /* id: name of key field */
    }
    strcpy(s->name, name);
}

struct my_struct *find_user(int user_id) {
    struct my_struct *s;

    HASH_FIND_INT(users, &user_id, s);  /* s: output pointer */
    return s;
}

void delete_user(struct my_struct *user) {
    HASH_DEL(users, user);  /* user: pointer to deletee */
    free(user);
}

void delete_all() {
  struct my_struct *current_user, *tmp;

  HASH_ITER(hh, users, current_user, tmp) {
    HASH_DEL(users, current_user);  /* delete it (users advances to next) */
    free(current_user);             /* free it */
  }
}

void print_users() {
    struct my_struct *s;

    for (s = users; s != NULL; s = (struct my_struct*)(s->hh.next)) {
        printf("user id %d: name %s\n", s->id, s->name);
    }
}

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

int id_sort(struct my_struct *a, struct my_struct *b) {
    return (a->id - b->id);
}

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

void sort_by_id() {
    HASH_SORT(users, id_sort);
}

int main(int argc, char *argv[]) {
    char in[10];
    int id = 1, running = 1;
    struct my_struct *s;
    unsigned num_users;

    while (running) {
        printf(" 1. add user\n");
        printf(" 2. add/rename user by id\n");
        printf(" 3. find user\n");
        printf(" 4. delete user\n");
        printf(" 5. delete all users\n");
        printf(" 6. sort items by name\n");
        printf(" 7. sort items by id\n");
        printf(" 8. print users\n");
        printf(" 9. count users\n");
        printf("10. quit\n");
        gets(in);
        switch(atoi(in)) {
            case 1:
                printf("name?\n");
                add_user(id++, gets(in));
                break;
            case 2:
                printf("id?\n");
                gets(in); id = atoi(in);
                printf("name?\n");
                add_user(id, gets(in));
                break;
            case 3:
                printf("id?\n");
                s = find_user(atoi(gets(in)));
                printf("user: %s\n", s ? s->name : "unknown");
                break;
            case 4:
                printf("id?\n");
                s = find_user(atoi(gets(in)));
                if (s) delete_user(s);
                else printf("id unknown\n");
                break;
            case 5:
                delete_all();
                break;
            case 6:
                sort_by_name();
                break;
            case 7:
                sort_by_id();
                break;
            case 8:
                print_users();
                break;
            case 9:
                num_users = HASH_COUNT(users);
                printf("there are %u users\n", num_users);
                break;
            case 10:
                running = 0;
                break;
        }
    }

    delete_all();  /* free any structures */
    return 0;
}

参考资料

uthash用户使用指南

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表是一种高效的数据结构,它可以在常数时间内完成插入、删除和查找操作。下面是一个简单的C语言哈希表代码和讲解: 代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include "uthash.h" struct hashTable { int key; int val; UT_hash_handle hh; }; struct hashTable *hashTable = NULL; void insert(int key, int val) { struct hashTable *s; HASH_FIND_INT(hashTable, &key, s); if (s == NULL) { s = (struct hashTable*)malloc(sizeof(struct hashTable)); s->key = key; HASH_ADD_INT(hashTable, key, s); } s->val = val; } int find(int key) { struct hashTable *s; HASH_FIND_INT(hashTable, &key, s); if (s == NULL) { return -1; } return s->val; } void delete(int key) { struct hashTable *s; HASH_FIND_INT(hashTable, &key, s); if (s != NULL) { HASH_DEL(hashTable, s); free(s); } } void printHashTable() { struct hashTable *s; for (s = hashTable; s != NULL; s = (struct hashTable*)(s->hh.next)) { printf("key:%d, val:%d\n", s->key, s->val); } } int main() { insert(1, 10); insert(2, 20); insert(3, 30); insert(4, 40); printf("find key 1, val:%d\n", find(1)); printf("find key 5, val:%d\n", find(5)); delete(3); printHashTable(); return 0; } ``` 讲解: 1. 首先定义了一个结构体`struct hashTable`,它含了键`key`和值`val`,以及一个`UT_hash_handle`类型的指针`hh`,这是一个用于哈希表操作的结构体。 2. 在`main`函数中,我们调用`insert`函数向哈希表中插入数据,调用`find`函数查找数据,调用`delete`函数删除数据,最后调用`printHashTable`函数打印哈希表中的所有数据。 3. `insert`函数首先调用`HASH_FIND_INT`宏查找哈希表中是否已经存在该键,如果不存在,则动态分配一个`struct hashTable`类型的结构体,并将键和结构体添加到哈希表中。 4. `find`函数同样调用`HASH_FIND_INT`宏查找哈希表中是否存在该键,如果存在,则返回对应的值,否则返回-1。 5. `delete`函数调用`HASH_FIND_INT`宏查找哈希表中是否存在该键,如果存在,则调用`HASH_DEL`宏删除该键和对应的结构体,并释放内存。 6. `printHashTable`函数遍历哈希表中的所有数据,并打印出键和值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值