c开源库uthash的使用

一、 uthash概述

  1. uthash是一个用c语言编写的开源库,使用宏实现了哈希表的增删改查等功能
  2. github地址https://github.com/troydhanson/uthash
  3. 官方文档http://troydhanson.github.io/uthash/userguide.html
  4. leetcode c编译器支持uthash
    —2019年4月8日更新----
    c开源库uthash的使用_第1张图片

二、 uthash使用

  1. 初始化
    • uthash需要用户定义自己的数据结构,一个包含UT_hash_handle hh的结构体
    • 还需要定义键和值(可选),这里将id作为key, name作为value
    struct my_struct {
        int id;                    /* key */
        char name[10];
        UT_hash_handle hh;         /* makes this structure hashable */
    };
    typedef struct my_struct HashNode;
    typedef struct my_struct *HashHead;
    
    
  2. 添加
    • 向hashtable中添加数据
    • key是int,可以使用 HASH_ADD_INT
    • key是字符串,可以使用 HASH_ADD_STR
    • key是指针,可以使用 HASH_ADD_PTR
    • 其它,可以使用 HASH_ADD,上述实际都是调用这个方法,不过简化了参数
    	void hashTabel_add(HashHead *head, HashNode *users) {
    		// id是key的属性名字,虽然很奇怪,实际作为宏参数会被替换掉
    		// 可以看下面源码,intfield会替换换成&((add)->fieldname)
    		if(!find_user(*head, users->id))
        		HASH_ADD_INT(*head, id, users);
    	}
    
    #define HASH_ADD_INT(head,intfield,add)                                          \
        HASH_ADD(hh,head,intfield,sizeof(int),add)
    #define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
      HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add)
    
  3. 替换
    • 与添加差不多,会在添加前,删除key相同的节点,再添加新的节点
    • 如果key是int,可以使用 HASH_REPLACE_INT
    void replace_user(HashHead *head, HashNode *newNode) {
        HashNode *oldNode = find_user(*head, newNode->id);
        if (oldNode)
            HASH_REPLACE_INT(*head, id, newNode, oldNode);
    }
    
  4. 查找
    • 根据key查找节点
    • 如果key是int,可以使用 HASH_FIND_INT
    HashNode *find_user(HashHead head, int user_id) {
    	HashNode *s;
    	HASH_FIND_INT(head, &user_id, s);  /* s: output pointer */
    	return s;
    }
    
  5. 删除
    • 删除节点
    • 使用 HASH_DEL
    void delete_user(HashHead *head,HashNode *user) {
        if (user) {
            HASH_DEL(*head, user);  /* user: pointer to deletee */
            free(user);             /* optional; it's up to you! */
        }
    }
    
  6. 计数
    • 统计节点数
    • 使用 HASH_COUNT
    int count_user(HashHead head) {
        return HASH_COUNT(head);
    }
    
  7. 遍历
    • 遍历节点
    • 可以用循环或者使用 HASH_ITER
    void print_user(HashHead head) {
        HashNode *s;
        printf("size is %d\n", count_user(head));
        for (s = head; s != NULL; s = s->hh.next) {
            printf("user id %d, name %s\n", s->id, s->name);
        }
    }
    void print_user_iterator(HashHead head) {
        HashNode *s, *tmp;
        printf("size is %d\n", count_user(head));
        HASH_ITER(hh, head, s, tmp) {
            printf("user id %d: name %s\n", s->id, s->name);
            /* ... it is safe to delete and free s here */
        }
    }
    
  8. 排序
    • 给节点排序,可以根据key或者value
    • 使用 HASH_SORT
    int name_sort(HashNode *a, HashNode *b) {
        return strcmp(a->name,b->name);
    }
    
    int id_sort(HashNode *a, HashNode *b) {
        return (a->id - b->id);
    }
    
    void sort_by_name(HashHead *head) {
        HASH_SORT(*head, name_sort);
    }
    
    void sort_by_id(HashHead *head) {
        HASH_SORT(*head, id_sort);
    }
    

三、完整代码

#include 
#include 
#include "uthash.h"

typedef struct my_struct {
    int id;            /* we'll use this field as the key */
    char name[10];
    UT_hash_handle hh; /* makes this structure hashable */
}HashNode;
typedef HashNode* HashHead;

int count_user(HashHead head);
HashNode *find_user(HashHead head, int user_id) {
    HashNode *s;
    HASH_FIND_INT(head, &user_id, s);  /* s: output pointer */
    return s;
}
void add_user(HashHead *head, HashNode *users) {
    if(!find_user(*head, users->id))
        HASH_ADD_INT(*head, id, users);
}
void replace_user(HashHead *head, HashNode *newNode) {
    HashNode *oldNode = find_user(*head, newNode->id);
    if (oldNode)
        HASH_REPLACE_INT(*head, id, newNode, oldNode);
}
void delete_user(HashHead *head,HashNode *user) {
    if (user) {
        HASH_DEL(*head, user);  /* user: pointer to deletee */
        free(user);             /* optional; it's up to you! */
    }
}
void print_user(HashHead head) {
    HashNode *s;
    printf("size is %d\n", count_user(head));
    for (s = head; s != NULL; s = s->hh.next) {
        printf("user id %d, name %s\n", s->id, s->name);
    }
}
void print_user_iterator(HashHead head) {
    HashNode *s, *tmp;
    printf("size is %d\n", count_user(head));
    HASH_ITER(hh, head, s, tmp) {
        printf("user id %d: name %s\n", s->id, s->name);
        /* ... it is safe to delete and free s here */
    }
}
int count_user(HashHead head) {
    return HASH_COUNT(head);
}
int name_sort(HashNode *a, HashNode *b) {
	   return strcmp(a->name,b->name);
}

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

void sort_by_name(HashHead *head) {
	   HASH_SORT(*head, name_sort);
}

void sort_by_id(HashHead *head) {
	   HASH_SORT(*head, id_sort);
}
int main()
{
    printf("--------------init---------------\n");
    HashHead head = NULL;
    printf("--------------add---------------\n");
    HashNode *node = malloc(sizeof(HashNode));
    node->id = 1;
    strcpy(node->name, "tom");
    add_user(&head, node);

    node = malloc(sizeof(HashNode));
    node->id = 2;
    strcpy(node->name, "jerry");
    add_user(&head, node);

    node = malloc(sizeof(HashNode));
    node->id = 3;
    strcpy(node->name, "jack");
    add_user(&head, node);

    node = malloc(sizeof(HashNode));
    node->id = 0;
    strcpy(node->name, "zero");
    add_user(&head, node);

    print_user(head);

    printf("--------------replace---------------\n");
    HashNode *newNode = malloc(sizeof(HashNode));
    newNode->id = 3;
    strcpy(newNode->name, "rose");
    replace_user(&head, newNode);
    print_user(head);

    printf("--------------delete---------------\n");
    delete_user(&head, find_user(head, 1));
    print_user(head);
    printf("--------------sort-by-id---------------\n");
    sort_by_id(&head);
    print_user(head);
    printf("--------------sort-by-name---------------\n");
    sort_by_name(&head);
    print_user(head);
    return 0;
}

你可能感兴趣的:(github,c)