数据结构--列表与列表项-FreeRTOS学习笔记

FreeRTOS 学习记录

#数据结构–列表与列表项-FreeRTOS

要点

  1. 什么是根节点、什么是索引指针。
  2. 几种列表项的常用操作。
  3. Keil5 仿真结果示意。
  4. 学习是在野火的配套书籍下进行。

根节点和索引指针个人理解

1.根节点:根节点可以看做一个独立的个体,它只在链表结构体被定义,在节点结构体不存在,我们把链表当做首尾相连的时候,根节点为一个中转站。它的上一个节点为你插入的最后一个节点,它的下一个节点为你首先插入的节点。因此,根节点为MiniListItem_t xListEnd; /* 链表最后一个节点 */。
2.索引指针,索引指针最初位置应该在根节点处,也就是xListEnd处,便于对链表进行遍历和处理。

几种链表、节点操作(附部分个人理解注释)

1、链表根节点初始化

void vListInitialise( List_t * const pxList )
{
	/* 将链表索引指针指向最后一个节点 */
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );

	/* 将链表最后一个节点的辅助排序的值设置为最大,确保该节点就是链表的最后节点 */
	pxList->xListEnd.xItemValue = portMAX_DELAY;

    /* 将最后一个节点的pxNext和pxPrevious指针均指向节点自身,表示链表为空 */
	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );

	/* 初始化链表节点计数器的值为0,表示链表为空 */
	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
}

2、节点初始化

void vListInitialiseItem( ListItem_t * const pxItem )
{
	/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表 */
	pxItem->pvContainer = NULL;
}

3、将节点插入到链表的尾部

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
	//last  --- --- index
	//last  ---new_last --- index
	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 )++;
}

4、节点按照升序排列插入到链表

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )//两个参数,一个是链表,一个是新节点。
{
	ListItem_t *pxIterator;//定义节点指针
	
	/* 获取节点的排序辅助值 */
	const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;//新节点的排序辅助值赋值给 xValueOfInsertion;

	/* 寻找节点要插入的位置 */
	if( xValueOfInsertion == portMAX_DELAY )//这个位置为最大值
	{
		pxIterator = pxList->xListEnd.pxPrevious;//节点指针为链表最后一个节点的上一个节点
	}
	else
	{
		for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd );
		     pxIterator->pxNext->xItemValue <= xValueOfInsertion; 
			 pxIterator = pxIterator->pxNext )//从第一个节点开始递增查找直到,节点指针的下一个节点的辅助值大于新节点
		                                    //辅助值,然后插入,pxIterator就是要插入的点。
		{
			/* 没有事情可做,不断迭代只为了找到节点要插入的位置 */			
		}
	}
 //类比于在最后插入节点的操作
	pxNewListItem->pxNext = pxIterator->pxNext;//赋值为新节点下一个节点
	pxNewListItem->pxNext->pxPrevious = pxNewListItem;//要插入的点的上一个节点 为新节点
	pxNewListItem->pxPrevious = pxIterator;
	pxIterator->pxNext = pxNewListItem;

	/* 记住该节点所在的链表 */
	pxNewListItem->pvContainer = ( void * ) pxList;

	/* 链表节点计数器++ */
	( pxList->uxNumberOfItems )++;
}

5、删除节点

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;//需要移除节点的下一个节点赋值为当前节点的位置
	//这两句话等同于移出节点上、下两个节点的连接

	/* Make sure the index is left pointing to a valid item. */
	if( pxList->pxIndex == pxItemToRemove )//如果链表的索引指针是要移出的节点
	{
		pxList->pxIndex = pxItemToRemove->pxPrevious;//该移出节点的上一个节点作为索引指针点。
	}

	/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表 */
	pxItemToRemove->pvContainer = NULL;//把该节点拿出该链表
	
	/* 链表节点计数器-- */
	( pxList->uxNumberOfItems )--;

	/* 返回链表中剩余节点的个数 */
	return pxList->uxNumberOfItems;
}

6、仿真图片
可以看出
可以看出根节点的下一个节点为第一个插入的节点。
在这里插入图片描述
可以看出根节点的上一个节点为最后一个插入的节点。

以上为个人学习后的理解,有错误之处请指出,互相交流。

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页