FreeRTOS笔记——C语言链表概念

在 FreeRTOS 中存在着大量的基础数据结构列表和列表项的操作,要想读懂 FreeRTOS的源码或者从 0到 1开始实现 FreeRTOS,就必须弄懂列表和列表项的操作。

链表作为 C 语言中一种基础的数据结构,在平时写程序的时候用的并不多,但在操作系统里面使用的非常多。链表就好比一个圆形的晾衣架,晾衣架上面有很多钩子,钩子首尾相连。链表也是,链表由节点组成,节点与节点之间首尾相连。晾衣架的钩子本身不能代表很多东西,但是钩子本身却可以挂很多东西。同样,链表也类似,链表的节点本身不能存储太多东西,或者说链表的节点本来就不是用来存储大量数据的,但是节点跟晾衣架的钩子一样,可以挂很多数据。

链表分为单向链表和双向链表,单向链表很少用,使用最多的还是双向链表。

单向链表 单向链表示意图如下。该链表中共有 n 个节点,前一个节点都有一个箭头指向后一个节点,首尾相连,组成一个圈。

节点本身必须包含一个节点指针,用于指向后一个节点,除了这个节点指针是必须有的之外,节点本身还可以携带一些私有信息,怎么携带?节点都是一个自定义类型的数据结构,在这个数据结构里面可以有单个的数据、数组、指针数据和自定义的结构体数据类型等等信息,代码如下:

struct node
{
          
   
	struct node *next; 			/* 指向链表的下一个节点 */
	char data1; 					/* 单个的数据 */
	unsigned char array[]; 	/* 数组 */
	unsigned long *prt  			/* 指针数据  */ 
	struct userstruct data2;	 /* 自定义结构体类型数据 */
 	/*...... */
 }

除了 struct node *next 这个节点指针之外,剩下的成员都可以理解为节点携带的数据,但是这种方法很少用。通常的做法是节点里面只包含一个用于指向下一个节点的指针。要通过链表存储的数据内嵌一个节点即可,这些要存储的数据通过这个内嵌的节点即可挂接到链表中,就好像晾衣架的钩子一样,把衣服挂接到晾衣架中,具体的伪代码实现如下:

/* 节点定义 */
struct node
{
          
   
	struct node *next; /* 指向链表的下一个节点 */
}

struct userstruct
{
          
   
 	/* 在结构体中,内嵌一个节点指针,通过这个节点将数据挂接到链表 */
	struct node *next;
	/* 各种各样......,要存储的数据 */
}

链表的操作 链表最大的作用是通过节点把离散的数据链接在一起,组成一个表。 链表常规的操作就是节点的插入和删除,为了顺利的插入,通常一条链表我们会人为地规定一个根节点,这个根节点称为生产者。通常根节点还会有一个节点计数器,用于统计整条链表的节点个数。

双向链表 双向链表与单向链表的区别就是节点中有两个节点指针,分别指向前后两个节点,其它完全一样。有关双向链表的文字描述参考单向链表小节即可,有关双向链表的示意图如下:

链表与数组的对比 链表是通过节点把离散的数据链接成一个表,通过对节点的插入和删除操作从而实现对数据的存取。而数组是通过开辟一段连续的内存来存储数据,这是数组和链表最大的区别。数组的每个成员对应链表的节点,成员和节点的数据类型可以是标准的 C 类型或者是用户自定义的结构体。数组有起始地址和结束地址,而链表是一个圈,没有头和尾之分,但是为了方便节点的插入和删除操作会人为的规定一个根节点。

经验分享 程序员 微信小程序 职场和发展