先来看看结点的数据结构:
struct _dnode
{
     union
    {
         struct _dnode *head;  /* 链表头指针 (sys_dlist_t) */
         struct _dnode *next;  /* 下一节点指针(sys_dnode_t) */
    };
     union
    {
         struct _dnode *tail;  /* 链表尾指针 (sys_dlist_t) */
         struct _dnode *prev;  /* 上一节点指针 (sys_dnode_t) */
    };
};

typedef  struct _dnode sys_dlist_t;  //表示链表,使用*head和*tail
typedef  struct _dnode sys_dnode_t;  //表示节点,使用*next和*prev
学过数据结构的都知道,链表本身就是用节点来表示的,这里只是使用共用体区分开来。

SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n)
/**
 * @brief 提供在一容器下的链表迭代原语
 * Note: 非安全循环,因此_cn不可或缺
 *
 * 用户必须自行添加大括号:
 *
 *     SYS_DLIST_FOR_EACH_CONTAINER(l, c, n) {
 *         <user code>
 *     }
 *
 * @param __dl  sys_dlist_t类型指针,指向将要迭代的链表
 * @param __cn  依次指向链表每个条目的指针
 * @param __n  容器中的sys_dnode_t类型成员名称
 */
#define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n)           \
     for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n); __cn; \
         __cn = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
此宏用于非安全遍历,所谓非安全遍历,就是不需要删除操作的遍历。要进行删除操作,就得使用下面这个宏了。

SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n)
/**
 * @brief 提供在一容器下的链表安全迭代原语
 * Note: __cn可用于删除,不会打断循环
 *
 * 用户必须自行添加大括号:
 *
 *     SYS_DLIST_FOR_EACH_CONTAINER_SAFE(l, c, cn, n) {
 *         <user code>
 *     }
 *
 * @param __dl  sys_dlist_t类型指针,指向将要迭代的链表
 * @param __cn  依次指向链表每个条目的指针
 * @param __cns  用于安全循环的指针
 * @param __n  sys_dnode_tsys_node_t在容器结构体中的类型名称
 */
#define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n)   \
     for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n), \
         __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n); __cn; \
         __cn = __cns,                      \
         __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
此宏用于安全遍历,也就是需要进行删除操作时,再使用此方法遍历。_cn可被删除。

sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
将node节点追加到 list链表尾部。

sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
将node节点插入到list链表头部。

sys_dlist_insert_after(sys_dlist_t *list,
sys_dnode_t *insert_point, 
sys_dnode_t *node)
将node节点插入到list链表的insert_point节点后面。

sys_dlist_insert_before(sys_dlist_t *list, 
sys_dnode_t *insert_point, 
sys_dnode_t *node)
将node节点插入到list链表的insert_point节点前面。

sys_dlist_insert_at(sys_dlist_t *list, 
sys_dnode_t *node,
int (*cond)(sys_dnode_t *, void *), 
void *data)
将node节点插入到list链表内,至于插入到哪个位置,由cond()函数决定。在运行时每个节点和data参数都会传递给cond()函数进行判断,如果cond()返回1,则插入到当前判断节点的前面。
如果链表为空,则node作为头节点添加,不经过conf()判断。
这函数写的,很新颖啊!不研究在什么情况下使用了,改天碰到再说。

sys_dlist_remove(sys_dnode_t *node)
删除节点node,这函数写的,怎么看着都不合逻辑,都不需要指定是哪个链表了。不过想想,的确也不需要指定链表。

研究完了,写个例子吧。多年经验,不写个例子,还真就没办法掌握,顶多也就是自认为掌握而已。为了省事,直接把上次的slist例子改为dlist版的吧。

#include <zephyr.h>
#include <misc/printk.h>
#include <misc/dlist.h>static sys_dlist_t list;
struct container_node
{sys_dnode_t node;int id;
};void PrintList(sys_dlist_t *list) //依次打印所有节点
{struct container_node *container;printk("print list node:\n");//注意,下面的参数node是container_node结构体中的字段名SYS_DLIST_FOR_EACH_CONTAINER(list, container, node){printk("node%d   ", container->id);}printk("\n\n");
}void main(void)
{struct container_node node1, node2, node3, node4, node5;node1.id = 1;node2.id = 2;node3.id = 3;node4.id = 4;node5.id = 5;sys_dlist_init(&list);//将5个节点加入链表sys_dlist_append(&list, &node1.node);sys_dlist_append(&list, &node2.node);sys_dlist_append(&list, &node3.node);sys_dlist_append(&list, &node4.node);sys_dlist_append(&list, &node5.node);PrintList(&list);printk("move node3 to head\n");sys_dlist_remove(&node3.node);//删除节点3sys_dlist_prepend(&list, &node3.node);//将节点3变为头节点PrintList(&list);printk("switch node4 and node2\n");sys_dlist_remove(&node4.node);//删除节点4sys_dlist_insert_after(&list, &node1.node, &node4.node);//将节点4加到节点1后面PrintList(&list);
}

运行结果如下图所示:

结果和slist的一模一样。两者的代码间的最大区别就是结点删除操作,大家可以做下对比。slist的是find and remove。而dlist的是直接remove。了解数据结构中单链表和双链表的区别,相信对这种区别的原因会有体会。

最后来个总结吧。个人观点,slist应该用在只对头尾进行操作的链表,比如作为栈和队列的基础数据结构就很合适。而如果要对链表中段进行操作,当然dlist会快很多。当然需要的内存也会大一些。

zephyr---双向链表dlist相关推荐

  1. zephyr学习笔记---双向链表dlist

    现阶段学zephyr很困难,没有足够资料,东一锤子,西一榔头,转来转去还是转回数据结构.没办法,这几个数据结构是其它各类机制的基础,不研究一下还真不行.静下心来先搞数据结构吧.上次讲了单向链表slis ...

  2. C语言一个双向链表的实现

    首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下: #ifndef DList_H #define DList_H typedef int Item; typedef struct ...

  3. Linux c 算法与数据结构--双向链表

    链表是linux c中非常重要的数据结构,双向链表与单向链表的区别,是它每个节点有两个指针域,分别指向该节点的前一个节点与后一个节点: 而链表的操作主要是查询.插入.删除.遍历等,下面来看一个双向链表 ...

  4. (第五章 1)组合——从DList到HashTable

    在HashTable中,用到了DList来解决冲突,我们不用重新实现其内部的DList,只需将已经实现的双向链表DList组合到HashTable中使用即可.下面给出工程的全部代码: 就不再解释其中每 ...

  5. php双向链表,双向链表的GO语言实现

    一.什么是双向链表 和单链表比较,双向链表的元素不但知道自己的下线,还知道自己的上线(越来越像传销组织了).小煤车开起来,图里面可以看出,每个车厢除了一个指向后面车厢的箭头外,还有一个指向前面车厢的箭 ...

  6. 数据结构 — 双向链表

    目录 文章目录 目录 双向链表 双向链表结点的数据结构 双向链表的操作集合 应用示例 创建双向链表 清理双向链表 查询链表结点 更新链表结点的数据 插入链表结点 删除结点 打印链表数据 双向链表 双向 ...

  7. 数据结构--双向链表

    双向链表的一种Go语言实现 package mainimport "fmt"//定义节点信息 type dNode struct {id intname stringpre *dN ...

  8. 用双向链表实现一个栈

    前面我们已经造好了一个轮子--双向链表,那么我们可以利用这个轮子做一个栈. 入栈:我们采用链表的头插 获得栈顶的元素:把头部元素拷贝到用户数据区 出栈:先把头部的元素拷贝到用户数据区,然后删除这个节点 ...

  9. Zephyr OS 内核篇: 内核链表

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/tidyjiang/article/details/52750485 Zephyr OS 所有的学习笔 ...

  10. 双向链表的创建和相关操作

    http://blog.csdn.net/jw903/article/details/38947753 双向链表其实是单链表的改进. 当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时, ...

最新文章

  1. id: cannot find name for user ID xxx处理办法
  2. Java发送邮件正文带表格
  3. c 用mysql导出xls文件怎么打开_mysql——xls表格的导出和导入(重点)
  4. 工业利用计算机实现生产自动化属于,自动化考试试题(含答案)
  5. keras 微调整模型_如何围绕微服务调整团队
  6. 计算机兴趣小组活动教学教案,长春一中计算机兴趣小组教案.ppt
  7. java02动手动脑
  8. 21. 包含min函数的栈(C++版本)
  9. 计算机组成原理与体系结构知识概括
  10. mugen linux主程序,MUGEN主程序
  11. char字符变量在c语言中有什么用,c语言char怎么用
  12. Facebook账号注册需要注意什么?Facebook养号技巧?
  13. 即时通讯IM,是时代进步的逆流?看看JNPF怎么说
  14. Sqlmap Tamper编写
  15. python使用ffmpeg库高效免费完成音频格式转换
  16. java程序员面试时候经常会问的一些问题_面试JAVA程序员常遇到的一些问题了解一下...
  17. 板材品牌排名之橱柜用生态板
  18. av_dump_format
  19. IP-Prefix List
  20. 将镭神C32激光雷达的PointXYZ数据转化为PointXYZIR格式 - 附代码

热门文章

  1. 虚拟机大剑服务器,《大剑》4日临界公测 Hold不住的火爆场面
  2. dedecms仿站入门视频教程
  3. css3 transition box-shadow 变为inset 不生效
  4. Hile每日算法-3.31-树形dp之换根法
  5. VNote 全文搜索
  6. web系统国际化方案
  7. 合肥各个区的发展特点
  8. 从“学习”到“引领”,源自中国的“渐变”会掀起新手机设计潮吗?
  9. 到底该不该去初创公司上班?
  10. substance painter 烘焙非pbr单张光照贴图