/* 将节点从链表中删除 */
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;
}
我们可以将这段代码比作在一个排队的人中间把某个人移走。想象一下每个人手里都有一个指向前面和后面人的指针,这样大家就能形成一个队列。下面是逐步的解释:
场景设定
假设我们有一个队列,里面的人的顺序是:
Alice -> Bob -> Charlie -> Dave
现在,我们要把中间的 Charlie
移走。
代码的执行过程
1. 找到要移走的人
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
- 我们先确定
Charlie
是在哪个队列(链表)中。每个人(节点)都有一个指向自己所在队列的指针。
2. 调整前后连接
现在,我们要把 Charlie
从队列中移除,保证 Alice
和 Dave
之间的连接不被打断。
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; // Dave's previous points to Bob
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; // Bob's next points to Dave
- 第一步:
Dave
(pxItemToRemove->pxNext
)要把他的指向前面的人改成Bob
(pxItemToRemove->pxPrevious
),这样Dave
就指向Bob
了。 - 第二步:
Bob
(pxItemToRemove->pxPrevious
)要把他的指向后面的人改成Dave
(pxItemToRemove->pxNext
),这样Bob
就指向Dave
了。
经过这两步,队列的顺序变成了:
Alice -> Bob -> Dave
这样,Charlie
被成功移走,队列仍然保持完整。
3. 更新索引
接下来,假设队列里有一个指针(索引)指向当前操作的对象,比如指向 Charlie
:
if( pxList->pxIndex == pxItemToRemove )
{
pxList->pxIndex = pxItemToRemove->pxPrevious; // 更新索引指向 Bob
}
- 如果队列的指针(
pxIndex
)指向了Charlie
,我们需要把它更新为Bob
,这样指针不会指向一个不存在的人。
4. 清空信息
pxItemToRemove->pvContainer = NULL;
- 我们将
Charlie
的队列指针设置为NULL
,表示他已经不在任何队列中,避免出现错误引用。
5. 更新队列长度
( pxList->uxNumberOfItems )--;
- 最后,我们把队列的总人数减 1,表示
Charlie
已经不在队列中了。
总结
在这段代码中,我们通过以下步骤从队列中移走一个人:
- 确定要移走的人(节点)所在的队列。
- 调整前后指向,确保前后的人可以正常连接。
- 如果需要,更新队列指向的当前节点,避免指向一个已删除的人。
- 清空被移走的人的队列信息,确保数据完整。
- 更新队列的总人数。