双向链表操作

/*******************************************************************************
*** Description: Simple doubly linked list implementation.
*******************************************************************************/
#ifndef __LIST_H__
#define __LIST_H__

/* 双向链表节点 */
typedef struct list_head
{
    struct list_head *next;
    struct list_head *prev;
} list_head_st;

/* 初始化节点 */
static inline void init_list_head(list_head_st *list)
{
    list->next = list;
    list->prev = list;
}

/* 添加节点: 将new插入到prev和next之间 */
static inline void __list_add(list_head_st *new, list_head_st *prev, list_head_st *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}

/* 添加new节点: 将new添加到head之后 */
static inline void list_add(list_head_st *new, list_head_st *head)
{
    __list_add(new, head, head->next);
}

/* 添加new节点: 将new添加到head之前, 即将new添加到双链表的末尾 */
static inline void list_add_tail(list_head_st *new, list_head_st *head)
{
    __list_add(new, head->prev, head);
}

static inline void __list_del(list_head_st *prev, list_head_st *next)
{
    next->prev = prev;
    prev->next = next;
}

/* 从双链表中删除entry节点 */
static inline void list_del(list_head_st *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = NULL;
    entry->prev = NULL;
}

/* 用new节点取代old节点 */
static inline void list_replace(list_head_st *old, list_head_st *new)
{
    new->next = old->next;
    new->next->prev = new;
    new->prev = old->prev;
    new->prev->next = new;
}

/* 双向链表是否为空 */
static inline int list_empty(const list_head_st *head)
{
    return head->next == head;
}

/* 获取"MEMBER成员"在"结构体TYPE"中的位置偏移 */
#define OFFSET_OF(type, member)  ((size_t) &((type *)0)->member)

/* 根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针 */
#define CONTAINER_OF(ptr, type, member)  ({ \
    const typeof(((type *)0)->member) *__mptr = (ptr); \
    (type *)((char *)__mptr - OFFSET_OF(type, member));})

/* 遍历双向链表 */
#define LIST_FOR_EACH(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

#define LIST_FOR_EACH_SAFE(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next)

/* 找出ptr指向的链表节点所在的type类型的结构体首地址 */
#define LIST_ENTRY(ptr, type, member) CONTAINER_OF(ptr, type, member)

#define LIST_FIRST_ENTRY(ptr, type, member)  LIST_ENTRY((ptr)->next, type, member)

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux内核双向链表是一种特殊的数据结构,它的设计初衷是为了解决不同数据类型作为链表数据节点对函数接口和封装的影响。具体操作双向链表的方法可以通过以下步骤实现: 1. 定义链表节点结构体:在使用双向链表之前,需要先定义链表节点的结构体。这个结构体需要包含一个前驱指针和一个后继指针,用来连接其他节点。 2. 初始化链表头:在使用链表之前,需要先初始化链表头。链表头是一个特殊的节点,它不存储具体的数据,只是一个用来指向链表的起始位置的指针。 3. 插入节点:要在链表插入一个新的节点,需要先将新节点的前驱指针和后继指针指向正确的位置,然后将原来的前驱节点和后继节点的指针指向新节点。 4. 删除节点:要从链表删除一个节点,需要将要删除节点的前驱节点的后继指针指向要删除节点的后继节点,将要删除节点的后继节点的前驱指针指向要删除节点的前驱节点。 5. 遍历链表:要遍历整个链表,可以从链表头开始,一直沿着后继指针向后遍历,直到到达链表尾部。 这些是操作Linux双向链表的一些基本方法,使用这些方法可以进行链表的插入、删除和遍历等操作。同时,Linux内核还提供了一些宏定义和函数来更方便地操作双向链表,比如container_of宏可以通过节点指针获取节点所在的结构体指针。 参考文献: linux 内核双向链表文件 首先介绍下双向链表的相关知识,最后有实战代码 container_of的定义在linux内核include/linux/kernel.h<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [linux源码内核双向链表文件](https://download.csdn.net/download/qq_18376583/86770056)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [linux 双向链表详解](https://blog.csdn.net/kksc1099054857/article/details/121717238)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值