数据结构零基础入门(初学者也能看懂):双向链表

15 篇文章 0 订阅
10 篇文章 0 订阅

数据结构设计

#define ADT_DLIST_DEF(s_name)                                                 \
    struct {                                                                  \
        struct s_name* next;                                                  \
        struct s_name* prev;                                                  \
    } DLIST

typedef struct AdtDList_s
{
    ADT_DLIST_DEF(AdtDList_s);     /**< List head */
} AdtDList_t;

【通用性】ADT_DLIST_DEF设计使得list_head自动适配各种业务数据。
【AdtDList_t】AdtDList_t作为业务数据中的list head。

接口实现

#define ADT_DLIST_NEXT(node) ((node)->DLIST.next)

#define ADT_DLIST_PREV(node) ((node)->DLIST.prev)

#define ADT_DLIST_HEAD_INIT(head)                                             \
    do {                                                                      \
        ADT_DLIST_NEXT(head) = (head);                                        \
        ADT_DLIST_PREV(head) = (head);                                        \
    } while(0)

#define ADT_DLIST_NODE_INIT(node)                                             \
    do {                                                                      \
        ADT_DLIST_NEXT(node) = NULL;                                          \
        ADT_DLIST_PREV(node) = NULL;                                          \
    } while(0)

#define ADT_DLIST_LINK_NEXT(link, node)                                       \
    do {                                                                      \
        ADT_DLIST_NEXT(node)                 = ADT_DLIST_NEXT(link);          \
        ADT_DLIST_PREV(node)                 = (link);                        \
        ADT_DLIST_NEXT(link)                 = (node);                        \
        ADT_DLIST_PREV(ADT_DLIST_NEXT(node)) = (node);                        \
    } while(0)

#define ADT_DLIST_LINK_PREV(link, node)                                       \
    do {                                                                      \
        ADT_DLIST_PREV(node)                 = ADT_DLIST_PREV(link);          \
        ADT_DLIST_NEXT(node)                 = (link);                        \
        ADT_DLIST_PREV(link)                 = (node);                        \
        ADT_DLIST_NEXT(ADT_DLIST_PREV(link)) = (node);                        \
    } while(0)

#define ADT_DLIST_UNLINK(link)                                                \
    do {                                                                      \
        ADT_DLIST_PREV(ADT_DLIST_NEXT(link)) = ADT_DLIST_PREV(link);          \
        ADT_DLIST_NEXT(ADT_DLIST_PREV(link)) = ADT_DLIST_NEXT(link);          \
        ADT_DLIST_NODE_INIT(link);                                            \
    } while(0)

#define ADT_DLIST_EACH_NEXT(head, link)                                       \
    for (link = head; (link = ADT_DLIST_NEXT(link)) != (head); )

#define ADT_DLIST_EACH_NEXT_SAFE(head, link, save)                      \
    for ((void) (link = ADT_DLIST_NEXT(head)), save = ADT_DLIST_NEXT(link) ; \
         link != (head);                                                \
         (void) (link = save), (void) (save = ADT_DLIST_NEXT(link)))

define ADT_DLIST_EACH_PREV(head, link)                                       \
    for (link = head; (link = ADT_DLIST_PREV(link)) != (head); )

#define ADT_DLIST_EACH_PREV_SAFE(head, link, save)                      \
    for ((void) (link = ADT_DLIST_PREV(head)), save = ADT_DLIST_PREV(link) ; \
         link != (head);                                                \
         (void) (link = save), (void) (save = ADT_DLIST_PREV(link)))

#define ADT_DLIST_IS_EMPTY(head) (ADT_DLIST_NEXT(head) == head)

#define ADT_DLIST_IS_LINKED(node) (ADT_DLIST_NEXT(node) != NULL)

【ADT_DLIST_LINK_NEXT】先处理新节点作为缓冲是比较明智又安全的做法。PREV操作是把所有NEXT和PREV对调。
【ADT_DLIST_EACH_NEXT】不可用在含删除节点操作的场景中。有删除节点操作,须使用:ADT_DLIST_EACH_NEXT_SAFE。安全的原因是tmp保存了被删除节点的元数据信息,可以使得循环链不会被断掉。

测试用例

typedef struct node_d_ {
    AdtDList_t dlink;

    int val;
} node_d;

int test_dlist()
{
    int i = 0;
    node_d *item = NULL;

    AdtDList_t dlist;
    AdtDList_t *dlink = NULL;

    ADT_DLIST_HEAD_INIT(&dlist);                            ///INIT

    for (i=0; i<10; i++) {
        item = (node_d *) malloc(sizeof(node_d));
        if (item) {
            memset(item, 0x0, sizeof(node_d));
            item->val = i;

            ADT_DLIST_NODE_INIT(&item->dlink);             ///INIT_NODE
            ADT_DLIST_LINK_PREV(&dlist, &item->dlink);     /// LINK
        }
        item = NULL;
    }

    ADT_DLIST_EACH_PREV(&dlist, dlink) {                  //LOOP
        node_d *node = container_of(dlink, node_d, dlink);
        printf("%d ", node->val);
    }
    printf("\n");

    //free TODO

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值