C语言链表的操作

初学

初学C语言时,对于链表节点的定义一般是这样的:

cpp 复制代码
typedef struct node {
    int data;
    struct node *next;
} Node;

向链表中添加节点:

cpp 复制代码
void addNode(Node **head, int data) {
    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = *head;
    *head = newNode;
}

删除节点和遍历节点,就不列举了

进阶

但是到了工作中,对链表的操作一般不这么玩

节点定义

工作中链表节点的定义:

cpp 复制代码
struct dlist {
    struct dlist *next;
    struct dlist *prev;
};

也就是说是一个双向链表

  • next 指向下一个节点
  • prev 指向上一个节点
  • 由于是 双向循环链表 ,最后一个节点的 next 指向头节点,头节点的 prev 指向最后一个节点

然后我们在实际使用时,一般定义一个包含struct dlist结构的自定义结构,例如

cpp 复制代码
struct my_struct {
    int data;
    struct dlist list;
};

初始化

在使用的时候,一般先初始化

cpp 复制代码
static inline void dlist_init(struct dlist *list)
{
    list->next = list;
    list->prev = list;
}

//调用这个接口,传入节点的地址即可
struct my_struct test;
dlist_init(&test.list);

添加节点

添加节点一般有两个接口:dlist_add和dlist_add_tail

cpp 复制代码
static inline void __dlist_add(struct dlist *entry, struct dlist *prev, struct dlist *next)
{
    entry->next = next;
    entry->prev = prev;
    next->prev = entry;
    prev->next = entry;
}

/* Add a new entry to the head of list */
static inline void dlist_add(struct dlist *list, struct dlist *entry)
{
    __dlist_add(entry, list, list->next);
}

/* Add a new entry to the tail of list */
static inline void dlist_add_tail(struct dlist *list, struct dlist *entry)

删除节点

删除节点调用dlist_del接口

cpp 复制代码
static inline void __dlist_del(struct dlist *entry)
{
    entry->next->prev = entry->prev;
    entry->prev->next = entry->next;
}

/* Delete an entry from list */
static inline void dlist_del(struct dlist *entry)
{
    __dlist_del(entry);
    entry->next = NULL;
    entry->prev = NULL;
}

遍历节点

遍历节点有dlist_for_each和dlist_for_each_entry,两者的区别参考:

linux之list_for_each和list_for_each_entry函数 - 裸睡的猪 - 博客园

cpp 复制代码
dlist_for_each
dlist_for_each_entry

还有一个是安全遍历,**在删除节点的时候使用。**不使用这个接口的话,不能直接对链表进行操作,只能读取

cpp 复制代码
dlist_for_each_entry_safe

通常我们要自定义一个结构体,然后结构体中包含 struct list_headlist_head 本质上就是链表中的一个节点,而且是一个 通用节点结构 ,用来把自己的结构体组织成链表。可以把 struct list_head 理解为"钩子",用来将节点一个个挂到链表上

参考:

Linux内核链表_linux的链表-CSDN博客

相关推荐
大模型玩家七七5 小时前
基于语义切分 vs 基于结构切分的实际差异
java·开发语言·数据库·安全·batch
历程里程碑5 小时前
Linux22 文件系统
linux·运维·c语言·开发语言·数据结构·c++·算法
牛奔6 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
寻星探路10 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
lly20240612 小时前
Bootstrap 警告框
开发语言
2601_9491465312 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧13 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX13 小时前
服务异步通信
开发语言·后端·微服务·ruby
zmzb010313 小时前
C++课后习题训练记录Day98
开发语言·c++
猫头虎14 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven