当前位置: 首页 > news >正文

双向链表的理解

背景

代码中经常会出现双向链表,对于双向链表的插入和删除有对应的API函数接口,但直观的图表更容易理解,所以本文会对rt-thread内核代码中提供的双向链表的一些API函数操作进行绘图,方便后续随时查看。

代码块

rt-thread中提供的代码段包括:
链表定义rtdef.h

/**
 * Double List structure
 */
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. */

API操作定义rtserver.h

/**
 * @addtogroup KernelService
 */

/**@{*/

/**
 * rt_container_of - return the start address of struct type, while ptr is the
 * member of struct type.
 */
#define rt_container_of(ptr, type, member) \
    ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))


/**
 * @brief initialize a list object
 */
#define RT_LIST_OBJECT_INIT(object) { &(object), &(object) }

/**
 * @brief initialize a list
 *
 * @param l list to be initialized
 */
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;
    n->next = l->next;

    l->next = n;
    n->prev = l;
}

/**
 * @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;
    n->prev = l->prev;

    l->prev = n;
    n->next = l;
}

/**
 * @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;
}

/**
 * @brief get the list length
 * @param l the list to get.
 */
rt_inline unsigned int rt_list_len(const rt_list_t *l)
{
    unsigned int len = 0;
    const rt_list_t *p = l;
    while (p->next != l)
    {
        p = p->next;
        len ++;
    }

    return len;
}

/**
 * @brief get the struct for this entry
 * @param node the entry point
 * @param type the type of structure
 * @param member the name of list in structure
 */
#define rt_list_entry(node, type, member) \
    rt_container_of(node, type, member)

/**
 * rt_list_for_each - iterate over a list
 * @pos:    the rt_list_t * to use as a loop cursor.
 * @head:   the head for your list.
 */
#define rt_list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

/**
 * rt_list_for_each_safe - iterate over a list safe against removal of list entry
 * @pos:    the rt_list_t * to use as a loop cursor.
 * @n:      another rt_list_t * to use as temporary storage
 * @head:   the head for your list.
 */
#define rt_list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)

/**
 * rt_list_for_each_entry  -   iterate over list of given type
 * @pos:    the type * to use as a loop cursor.
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define rt_list_for_each_entry(pos, head, member) \
    for (pos = rt_list_entry((head)->next, typeof(*pos), member); \
         &pos->member != (head); \
         pos = rt_list_entry(pos->member.next, typeof(*pos), member))

/**
 * rt_list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:    the type * to use as a loop cursor.
 * @n:      another type * to use as temporary storage
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define rt_list_for_each_entry_safe(pos, n, head, member) \
    for (pos = rt_list_entry((head)->next, typeof(*pos), member), \
         n = rt_list_entry(pos->member.next, typeof(*pos), member); \
         &pos->member != (head); \
         pos = n, n = rt_list_entry(n->member.next, typeof(*n), member))

/**
 * rt_list_first_entry - get the first element from a list
 * @ptr:    the list head to take the element from.
 * @type:   the type of the struct this is embedded in.
 * @member: the name of the list_struct within the struct.
 *
 * Note, that list is expected to be not empty.
 */
#define rt_list_first_entry(ptr, type, member) \
    rt_list_entry((ptr)->next, type, member)

重点函数

rt_list_init()
rt_list_insert_after()
rt_list_insert_before()
rt_list_remove()

重点函数理解

rt_list_init(rt_list_t *l)

rt_inline void rt_list_init(rt_list_t *l)
{
    l->next = l->prev = l;
}

初始化当前链表l,即当前链表l的pre和next都是指向自己。
在这里插入图片描述

rt_list_insert_after(rt_list_t *l, rt_list_t *n)

rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
    l->next->prev = n;
    n->next = l->next;

    l->next = n;
    n->prev = l;
}

将新链表n1插入到l之后
在这里插入图片描述
将新链表n2插入到l之后
在这里插入图片描述
将新链表n3插入到l之后
在这里插入图片描述

rt_list_insert_before(rt_list_t *l, rt_list_t *n)

rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{
    l->prev->next = n;
    n->prev = l->prev;

    l->prev = n;
    n->next = l;
}

将新链表n1插入到l之前
在这里插入图片描述
将新链表n2插入到l之前
在这里插入图片描述

rt_list_remove(rt_list_t *n)

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;
}

从已有链表中移除当前链表,如原链表
在这里插入图片描述
从此链表中移除n2,则
在这里插入图片描述

相关文章:

  • 【Kettle安装】Kettle安装过程, 电脑已安装java23,安装Kettle 出现报错:尝试启动 Java 虚拟机(JVM)时失败解决方法
  • JavaEE-MyBatis概述第一个程序
  • Redis GEO
  • [7-02-02].第15节:生产经验 - 消费者相关操作
  • 农产品直卖平台的设计与实现(代码+数据库+LW)
  • Burpsuite 伪造 IP
  • 数据结构与算法:二维动态规划
  • 图解AUTOSAR_SWS_CANDriver
  • 【区块链安全 | 第二十四篇】单位和全局可用变量(二)
  • 翻译: 人工智能如何让世界变得更美好四
  • BERT与Transformer到底选哪个-下部
  • css_z-index属性
  • C++STL---<functional>
  • 如何使用fiddler抓取手机APP的包,进行前后端bug定位
  • pyproj 库中Geod类—geod.npts()方法讲解
  • 智能制造:MES系统架构设计
  • github合并多个commit message以及rebase解决文件冲突
  • cisco简单DHCP配置
  • 第三章:ROS基础_《ROS机器人开发实践》_notes
  • 【全队项目】智能学术海报生成系统PosterGenius--风格个性化调整
  • 国外网站建设素材/关键词优化怎么弄
  • 做网站python和php哪个好学/如何设计一个网站页面
  • 做网站一天能赚多少钱/seo博客写作
  • 如何用手机号做WordPress/seo网络优化
  • 做赌博网站的代理算赌博罪吗/正规营销培训
  • 湛江网站建设公司/seo到底是做什么的