list.h
struct list_head { struct list_head *prev; struct list_head *next; }; #define LIST_HEAD(head) struct list_head head = {&head, &head} static inline void INIT_LIST_HEAD(struct list_head *node) { node->prev = node; node->next = node; } static inline void __list_add(struct list_head *node, struct list_head *prev, struct list_head *next) { node->prev = prev; node->next = next; prev->next = node; next->prev = node; } static inline void list_add(struct list_head *node, struct list_head *head) { __list_add(node, head, head->next); } static inline void list_add_tail(struct list_head *node, struct list_head *head) { __list_add(node, head->prev, head); }
static inline int list_emtpy(struct list_head *head) { return head->next == head; } static inline void list_del(struct list_head *node) { node->prev->next = node->next; node->next->prev = node->prev; } static inline void list_del_init(struct list_head *node) { list_del(node); INIT_LIST_HEAD(node); } #define offsetof(type, member) \ ((size_t)(&((type*)0)->member)) #define container_of(ptr, type, member) \ ((type*)((char*)ptr - offsetof(type, member))) /* @cur: ?..list_head?..?.复?舵.? * @head: 澶磋.?圭.?板. */ #define list_for_each(cur, head) \ for (cur = (head)->next; \ (cur) != (head); \ cur = (cur)->next)
#define list_for_each_safe(cur, tmp, head) \ for (cur = (head)->next, tmp = (cur)->next; \ (cur) != (head); \ cur = tmp, tmp = (tmp)->next) /* @ptr: ?..list_head?..??ㄧ.澶х??.??..?.复?舵.? * @head: 澶磋.?圭.?板. */ #define list_for_each_entry(ptr, head, member) \ for ( ptr = container_of((head)->next, typeof(*(ptr)), member); \ &(ptr)->member != (head); \ ptr = container_of((ptr)->member.next, typeof(*(ptr)), member) ) #define list_for_each_entry_safe(ptr, tmp, head, member) \ for ( ptr = container_of((head)->next, typeof(*(ptr)), member); \ (&(ptr)->member != (head)) && (tmp = container_of((ptr)->member.next, typeof(*(ptr)), member)); \ ptr = tmp ) #define list_for_each_continue(cur, head) \ for (cur = (cur)->next; \ (cur) != (head); \ cur = (cur)->next) #define list_for_each_reverse(cur, head) \ for (cur = (head)->prev; \ (cur) != (head); \ cur = (cur)->prev)
hashtab.h
#include "list.h" struct hash_info { struct list_head *tab; size_t size; size_t (*hash)(struct hash_info *, struct list_head *); int (*key_cmp)(struct list_head *, struct list_head *); void (*add)(struct hash_info *, struct list_head *); void (*del)(struct hash_info *, struct list_head *); struct list_head *(*search)(struct hash_info *, struct list_head *key); }; void hash_init(struct hash_info *, size_t size, size_t (*hash)(struct hash_info *, struct list_head *), int (*key_cmp)(struct list_head *, struct list_head *)); void hash_destroy(struct hash_info *); ~
hashtab.c
#include <stdio.h> #include <stdlib.h> #include "hashtab.h" static void hash_add(struct hash_info *info, struct list_head *node) { size_t hash_val = info->hash(info, node); list_add_tail(node, &info->tab[hash_val]); } /* hash_del: ?..?.复?惰.??ey?ユ.?稿.?抽.瀛..??..? * @key: 瀛..?..?抽.瀛..瀹瑰.锛.?涓.复?跺.?.??..?板.浣跨.浠.ode涓..?虹.?抽.瀛.?涓哄.?ゆ.浠 */ static void hash_del(struct hash_info *info, struct list_head *key) { size_t hash_val = info->hash(info, key); struct list_head *cur = NULL; struct list_head *tmp = NULL; list_for_each_safe(cur, tmp, &info->tab[hash_val]) { if (info->key_cmp(cur, key)) { list_del_init(cur); } } }
static struct list_head *hash_search(struct hash_info *info, struct list_head *key_node) { static struct list_head *cur = NULL; static size_t hash_val = 0; if (!cur || !info->key_cmp(cur, key_node)) { hash_val = info->hash(info, key_node); cur = &info->tab[hash_val]; } list_for_each_continue(cur, &info->tab[hash_val]) { if (info->key_cmp(cur, key_node)) { return cur; } } return NULL; }
void hash_init(struct hash_info *info, size_t size, size_t (*hash)(struct hash_info *, struct list_head *), int (*key_cmp)(struct list_head *, struct list_head *)) { info->tab = (struct list_head *)malloc(sizeof(struct list_head) * size); size_t i = 0; for (i = 0; i < size; i++) { INIT_LIST_HEAD(&info->tab[i]); } info->size = size; info->hash = hash; info->key_cmp = key_cmp; info->add = hash_add; info->del = hash_del; info->search = hash_search; } void hash_destroy(struct hash_info *info) { struct list_head *cur = NULL; struct list_head *tmp = NULL; size_t i = 0; for (i = 0; i < info->size; i++) { list_for_each_safe(cur, tmp, &info->tab[i]) { list_del_init(cur); } } free(info->tab); }
test.c
#include <stdio.h> #include <string.h> #include "hashtab.h" struct node_info { const char *name; size_t age; struct list_head list; }; static size_t hash_func(struct hash_info *info, struct list_head *node) { struct node_info *cur = container_of(node, struct node_info, list); size_t hash_val = 0; const char *p = cur->name; for (; *p; ++p) { hash_val += *p; } return hash_val % info->size; } static int key_cmp(struct list_head *a, struct list_head *b) { struct node_info *pa = container_of(a, struct node_info, list); struct node_info *pb = container_of(b, struct node_info, list); return !strcmp(pa->name, pb->name); }
int main() { struct node_info s[] = { {"kate", 20}, {"kate", 28}, {"mike", 24}, {"kelly", 19}, {"mike", 23}, {"kate", 20}, {"tom", 23}, {"kate", 22}, {"jack", 24}, {"tom", 24}, {"john", 25}, {"peter", 27}, }; struct hash_info hash; hash_init(&hash, 5, hash_func, key_cmp); size_t i = 0; for (i = 0; i < sizeof(s) / sizeof(struct node_info); ++i) { hash.add(&hash, &s[i].list); } struct node_info tmp = {0}; tmp.name = s[0].name; //kate /* hash.del(&hash, &tmp.list);*/ struct list_head *cur = NULL; struct node_info *ptr = NULL;
while (cur = hash.search(&hash, &tmp.list)) { ptr = container_of(cur, struct node_info, list); printf("%s: %ld\n", ptr->name, ptr->age); } cur = hash.search(&hash, &tmp.list); ptr = container_of(cur, struct node_info, list); printf("%s: %ld\n", ptr->name, ptr->age); tmp.name = s[2].name; //mike while (cur = hash.search(&hash, &tmp.list)) { ptr = container_of(cur, struct node_info, list); printf("%s: %ld\n", ptr->name, ptr->age); } hash_destroy(&hash); return 0; }