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博客

相关推荐
Scott9999HH5 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社6 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海6 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖7 小时前
JDK 26 新特性详解
java·开发语言
马优晨8 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区10 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大10 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai11 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜11 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa11 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio