当前位置: 首页 > article >正文

C语言链表的操作

初学

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

typedef struct node {int data;struct node *next;
} Node;

向链表中添加节点:

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

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

进阶

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

节点定义

工作中链表节点的定义:

struct dlist {struct dlist *next;struct dlist *prev;
};

也就是说是一个双向链表

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

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

struct my_struct {int data;struct dlist list;
};

初始化

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

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

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接口

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函数 - 裸睡的猪 - 博客园

dlist_for_each
dlist_for_each_entry

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

dlist_for_each_entry_safe

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

参考:

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

http://www.lryc.cn/news/2379104.html

相关文章:

  • 芯片生态链深度解析(二):基础设备篇——人类精密制造的“巅峰对决”
  • C语言指针深入详解(二):const修饰指针、野指针、assert断言、指针的使用和传址调用
  • 【unity游戏开发——编辑器扩展】使用EditorGUI的EditorGUILayout绘制工具类在自定义编辑器窗口绘制各种UI控件
  • Linux基础第三天
  • MoodDrop:打造一款温柔的心情打卡单页应用
  • 接口——类比摄像
  • 【上位机——WPF】布局控件
  • 深入解析Spring Boot与Kafka集成:构建高性能消息驱动应用
  • 二十、案例特训专题3【系统设计篇】web架构设计
  • 【数据结构与算法】ArrayList 与顺序表的实现
  • 处理金融数据,特别是股票指数数据,以计算和分析RSRS(相对强度指数)
  • 【图像处理基石】OpenCV中都有哪些图像增强的工具?
  • WPS PPT设置默认文本框
  • PostGIS实现矢量数据转栅格数据【ST_AsRaster】
  • FAST-DDS源码分析PDP(一)
  • python打卡day29@浙大疏锦行
  • 【数据结构】2-3-1单链表的定义
  • 贝塞尔曲线原理
  • 3D个人简历网站 4.小岛
  • 创建型:原型模式
  • 浅谈“量子计算应用:从基础原理到行业破局”
  • Java面试攻略:从Spring Boot到微服务架构的深入探讨
  • 关于文件分片的介绍和应用
  • Tapered Off-Policy REINFORCE_ 如何为LLM实现稳定高效的策略优化?
  • 使用lvm进行磁盘分区
  • [Java实战]Spring Boot整合Elasticsearch(二十六)
  • 图像分割(1)U-net
  • 数位和:从定义到编程实现
  • 2025抓包工具Reqable手机抓包HTTPS亲测简单好用-快速跑通
  • 使用 Auto-Keras 进行自动化机器学习