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

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.dtcms.com/a/197517.html

相关文章:

  • Office 中 VBE 的共同特点与区别
  • 【C++】unordered_map与set的模拟实现
  • Atcoder Beginner Contest 406
  • 【基于Spring Boot 的图书购买系统】深度讲解 用户注册的前后端交互,Mapper操作MySQL数据库进行用户持久化
  • 程序代码篇---数据包解析
  • 层次原理图
  • Android开发——原生渲染方案实现 PDF 预览功能
  • Elasticsearch 初步认识
  • C++控制结构详解:if-else、switch、循环(for/while/do-while)
  • MySQL事务的一些奇奇怪怪知识
  • React-Query使用react-testing-library进行测试
  • 【RabbitMQ】 RabbitMQ高级特性(二)
  • Python高级特性深度解析:从熟练到精通的跃迁之路
  • 【老马】离线版金融敏感信息加解密组件开源项目 encryption-local
  • 实战设计模式之状态模式
  • React 19中useContext不需要Provider了。
  • numpy数组的拆分和组合
  • Python 装饰器详解
  • 使用 C# 入门深度学习:线性代数详细讲解
  • 3:OpenCV—视频播放
  • MySQL--day2--基本的select语句
  • Ubuntu16.04升级gcc/g++版本方法
  • [特殊字符] SSL/TLS 中的密钥协商流程笔记
  • 【图像生成大模型】HunyuanVideo:大规模视频生成模型的系统性框架
  • Vue百日学习计划Day28-32天详细计划-Gemini版
  • 泰国SAP ERP实施如何应对挑战?工博科技赋能中企出海EEC战略
  • 机器学习-人与机器生数据的区分模型测试 - 模型选择与微调
  • 第三章:UI 系统架构拆解与动态界面管理实录
  • Android动态音频柱状图可视化解析:从原理到实现
  • 【爬虫】DrissionPage-7