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;
}