从零开始掌握FreeRTOS(3)链表之插入和删除节点

 目录

插入节点

节点插入到尾部

节点升序排列插入

删除节点


    上篇文章介绍了 FreeRTOS 关于链表的基本概念,本篇将介绍如何插入和删除节点。

插入节点

        节点插入链表,首先需要在要插入位置断开两个节点的连接,然后将插入节点和这两个节点分别连接。前后效果如下图。

45b7594b0cf04522902af3de0e9a0bbc.png

 以下为节点插入过程演示。

让新节点的next指向根节点;

c9c7f3dfb70c4f07adfdc628ee6c84e0.png

 让新节点的previous指向根节点的上一个节点;

5452e067049e43b3a8a670d10c7fd256.png

让根节点的上一个节点的next指向新节点;

6478bcccf5c34104a25500e756abbdd2.png 让根节点的previous指向新节点;

c9e850041a2d4f35b22cb5cfcc9adb61.png

节点插入到尾部

 此方法可以将节点插入到一个空的链表中,也就是将节点和根节点连接在一起,这个过程分为以下几个步骤:

        1. 让根节点的下一个节点指向新节点。

        2. 让根节点的上一个节点指向新节点。

        3. 调整其他参数,使其根据实际情况进行调整。

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
    ListItem_t * const pxIndex = pxList->pxIndex;

	pxNewListItem->pxNext = pxIndex;
	pxNewListItem->pxPrevious = pxIndex->pxPrevious;

	pxIndex->pxPrevious->pxNext = pxNewListItem;
	pxIndex->pxPrevious = pxNewListItem;

	pxNewListItem->pvContainer = ( void * ) pxList;

	( pxList->uxNumberOfItems )++;
}

上述代码所做的操作如下:

        1. 将根节点的索引指针指向根节点的最后一个节点(即精简节点)。

        2. 新节点的 pxNext 指向索引指针,即指向根节点。

        3. 新节点的 pxPrevious 指向根节点。

        4. 根节点的 pxNext  指向新节点。

        5. 根节点的 pxPrevious 指向新节点。

        6. 新节点的 pvContainer 指向根节点。

        7. 根节点的节点计数器加1。

节点升序排列插入

        这种插入方法依赖于 xItemValue ,也就是每个节点的序号。因此,我们在执行完新节点的初始化之后,需要为新节点的 xItemValue 赋值。

        从根节点的下一个节点开始,xItemValue 的值越来越大,呈升序排列。根据这个序号的值找到应该插入的位置后,就会插入到链表中;如果链表存在和新节点序号一样的节点,则新节点会插入到这个节点的后面。

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
    ListItem_t *pxIterator;
    const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;

	if( xValueOfInsertion == portMAX_DELAY )
	{
		pxIterator = pxList->xListEnd.pxPrevious;
	}
	else
	{

		for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); 
            pxIterator->pxNext->xItemValue <= xValueOfInsertion;
            pxIterator = pxIterator->pxNext ) 
		{

		}
	}

	pxNewListItem->pxNext = pxIterator->pxNext;
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;
	pxNewListItem->pxPrevious = pxIterator;
	pxIterator->pxNext = pxNewListItem;

	pxNewListItem->pvContainer = ( void * ) pxList;

	( pxList->uxNumberOfItems )++;
}

         首先,获取新节点的序号,如果序号值等于节点数量的最大值,那么这个节点就会插入到根节点的前面;反之,则通过for循环来寻找要插入的位置。

        当找到要插入位置之后,将节点插入,然后更新插入节点的 pvContainer 和根节点的节点计数器。

删除节点

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
    List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;

	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

	if( pxList->pxIndex == pxItemToRemove )
	{
		pxList->pxIndex = pxItemToRemove->pxPrevious;
	}

	pxItemToRemove->pvContainer = NULL;
	( pxList->uxNumberOfItems )--;

	return pxList->uxNumberOfItems;
}

整个函数流程如下:

        1. 首先获取要删除节点所在的链表;

        2. 使要删除节点的下一个节点的previous指向要删除节点的上一个节点;

        3. 使要删除节点的上一个节点的next指向要删除节点的下一个节点;

        4. 调整将该链表的节点索引指针;

        5. 初始化要删除节点所在的链表为空,表示节点还没有插入任何链表;

        6. 然后将节点计数器减一并返回。

        删除节点的整个过程大致和插入节点相反,一个是指向插入节点,一个是指向该节点的上一个节点。

        到这一步为止,链表内容暂时告一段落。下一部分为任务的相关内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pQAQqa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值