RT-thread 双链表说明
说双向链表之前先简单说下单链表
单链表结点结构
数据域 | 引用域 |
---|---|
data | next |
- data:把存储据元素本身信息的域叫结点的数据域
- next:存储与它相邻的数据元素的存储地址信息的域叫结点的引用域
线性表(a 1 ,a 2 ,a 3 ,a 4 ,a 5 ,a 6 )对应的链式存储结构示意图。
- 头引用地址为800H
| 存储地址 | data | next |
| :—: | :—: | :----😐
| 909 | a4 | 600 |
| 900 | a2 | 709 |
| 600 | a5 | NULL |
| 800 | a1 | 900 |
| 709 | a3 | 909 |
双向链表结点的定义与单链表的结点的定义很相似,只是双向链表多了一个字段 prev。
双向链表结点结构
引用域 | 数据域 | 引用域 |
---|---|---|
prev | data | next |
- prev:保存直接前驱结点的地址
- data:把存储据元素本身信息的域叫结点的数据域
- next:保存直接后继结点的地址
prev | 存储地址 | data | next |
---|---|---|---|
709 | 909 | a4 | 600 |
800 | 900 | a2 | 709 |
900 | 600 | a5 | 600 |
800 | 800 | a1 | 900 |
900 | 709 | a3 | 909 |
双向链表的定义
struct rt_list_node
{
struct rt_list_node *next; /**< point to next node. */
struct rt_list_node *prev; /**< point to prev node. */
};
typedef struct rt_list_node rt_list_t; /**< Type for lists. */
链表初始化
- 将前后引用域都指向同一个地址
rt_inline void rt_list_init(rt_list_t *l)
{
l->next = l->prev = l;
}
双向链表后插入
/**
* @brief insert a node after a list
*
* @param l list to insert it
* @param n new node to be inserted
*/
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
l->next->prev = n; //(1)
n->next = l->next; //(2)
l->next = n; //(3)
n->prev = l; //(4)
}
- 图示
双向链表前插入
/**
* @brief insert a node before a list
*
* @param n new node to be inserted
* @param l list to insert it
*/
rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{
l->prev->next = n; //(1)
n->prev = l->prev; //(2)
l->prev = n; //(3)
n->next = l; //(4)
}
- 图示
按评论说这个图的箭头反了,实际也确实方向反了,找不到原图了,大家忽略方向吧,抱歉。
移除链表n结点
/**
* @brief remove node from list.
* @param n the node to remove from the list.
*/
rt_inline void rt_list_remove(rt_list_t *n)
{
n->next->prev = n->prev;
n->prev->next = n->next;
n->next = n->prev = n;
}
- 图示
检查是否为空链表
/**
* @brief tests whether a list is empty
* @param l the list to test.
*/
rt_inline int rt_list_isempty(const rt_list_t *l)
{
return l->next == l;
}