05list-hlist

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) \
    ({const typeof(((type*)0)->member) *__mptr = ptr; \
     (type*)((char*)__mptr - 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)

struct hlist_node {
    struct hlist_node *next;
    struct hlist_node **pprev;
};

struct hlist_head {
    struct hlist_node *first;
};

#define HLIST_HEAD(head) struct hlist_head head = {NULL}

static inline void INIT_HLIST_HEAD(struct hlist_head *head)
{
    head->first = NULL;
}

static inline void INIT_HLIST_NODE(struct hlist_node *node)
{
    node->next = NULL;
    node->pprev = NULL;
}

static inline void hlist_add_head(struct hlist_node *node,
        struct hlist_head *head)
{
    node->next = head->first;
    node->pprev = &head->first;
    head->first = node;
    if (node->next) {
        node->next->pprev = &node->next;
    }
}

static inline void hlist_add_before(struct hlist_node *node, struct hlist_node *next)
{
    node->next = next;
    node->pprev = next->pprev;
    *node->pprev = node;
    next->pprev = &node->next;
}

static inline void hlist_add_after(struct hlist_node *prev,
        struct hlist_node *node)
{
    node->next = prev->next;
    node->pprev = &prev->next;
    prev->next = node;
    if (node->next) {
        node->next->pprev = &node->next;
    }
}

static inline void hlist_del(struct hlist_node *node)
{
    *node->pprev = node->next;
    if (node->next) {
        node->next->pprev = node->pprev;
    }
}

static inline void hlist_del_init(struct hlist_node *node)
{
    hlist_del(node);
    INIT_HLIST_NODE(node);
}

static inline int hlist_empty(struct hlist_head *head)
{
    return head->first == NULL;
}

#define hlist_for_each(cur, head) \
    for (cur = (head)->first; \
        cur; cur = (cur)->next)

#define hlist_for_each_safe(cur, tmp, head) \
    for (cur = (head)->first; \
        cur && ({tmp = (cur)->next; 1;}); \
        cur = tmp)

#define hlist_for_each_continue(cur, head) \
    for (cur = (cur)->next; \
        cur; cur = (cur)->next)

#define hlist_for_each_from(cur, head) \
    for (; cur; cur = (cur)->next)

#define hlist_for_each_entry(ptr, cur, head, member) \
    for (cur = (head)->first; \
        cur && (ptr = container_of(cur, typeof(*(ptr)), member)); \
        cur = (cur)->next)

#define hlist_for_each_entry_safe(ptr, cur, tmp, head, member) \
    for (cur = (head)->first; \
        cur && (tmp = (cur)->next, 1) && \
        (ptr = container_of(cur, typeof(*(ptr)), member)); \
        cur = tmp)


hashtab.h

#include "list.h"

struct hash_info {
    struct hlist_head *tab;
    size_t size;
    size_t (*hash)(struct hash_info *,  
            struct hlist_node *); 
    int (*key_cmp)(struct hlist_node *,
            struct hlist_node *); 
    void (*add)(struct hash_info *,
            struct hlist_node *); 
    void (*del)(struct hash_info *,
            struct hlist_node *); 
    struct hlist_node *(*search)(struct hash_info *,
            struct hlist_node *key);
};

void hash_init(struct hash_info *, size_t size,
        size_t (*hash)(struct hash_info *,
            struct hlist_node *), 
        int (*key_cmp)(struct hlist_node *,
            struct hlist_node *));
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 hlist_node *node)
{
    size_t hash_val = info->hash(info, node);

    hlist_add_head(node, &info->tab[hash_val]);
}

/* hash_del: ?..?.复?惰.??ey?ユ.?稿.?抽.瀛..?€?..?
 * @key: 瀛..?..?抽.瀛..瀹瑰.锛.?涓.复?跺.?.??..?板.浣跨.浠.ode涓..?虹.?抽.瀛.?涓哄.?ゆ.浠
 */
static void hash_del(struct hash_info *info,
        struct hlist_node *key)
{
    size_t hash_val = info->hash(info, key);

    struct hlist_node *cur = NULL;
    struct hlist_node *tmp = NULL;
    hlist_for_each_safe(cur, tmp, &info->tab[hash_val]) {
        if (info->key_cmp(cur, key)) {
            hlist_del_init(cur);
        }
    }
}


 

static struct hlist_node *hash_search(struct hash_info *info, struct hlist_node *key_node)
{
    static struct hlist_node *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].first;
        if (!cur) {
            return NULL;
        } else if (info->key_cmp(cur, key_node)) {
            return cur;
        }
    }

    hlist_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 hlist_node *),
        int (*key_cmp)(struct hlist_node *,
            struct hlist_node *))
{
    info->tab = (struct hlist_head *)malloc(sizeof(struct hlist_head) * size);
    size_t i = 0;
    for (i = 0; i < size; i++) {
        INIT_HLIST_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 hlist_node *cur = NULL;
    struct hlist_node *tmp = NULL;

    size_t i = 0;
    for (i = 0; i < info->size; i++) {
        hlist_for_each_safe(cur, tmp, &info->tab[i]) {
            hlist_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 hlist_node list;
};

static size_t hash_func(struct hash_info *info,
        struct hlist_node *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 hlist_node *a,
        struct hlist_node *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 hlist_node *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);
    }

    tmp.name = s[6].name; //tom
    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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值