这两天有兴趣学习使用了下系统头文件sys/queue.h中的链表/队列的实现,感觉实现的很是优美,关键是以后再也不需要自己实现这些基本的数据结构了,哈哈!

我的系统环境是

正好需要使用队列,那么本篇就以其中的尾队列(tail queue)为例,结合实际的测试程序和示意图(亿图软件)来说明。

测试程序tailq.c如下:

#include <stdio.h>  
#include <stdlib.h>  
#include <sys/queue.h>  
 
struct _Data {  
    int                 value;  
    TAILQ_ENTRY(_Data)  tailq_entry;  
};  
 
int main(int argc, const char *argv[])  
{  
    /* 1. 初始化队列 */  
#if 0  
    TAILQ_HEAD(tailq_head, _Data)   head = TAILQ_HEAD_INITIALIZER(head);  
#else  
    TAILQ_HEAD(tailq_head, _Data)   head;  
    TAILQ_INIT(&head);  
#endif  
    int i;  
    struct _Data *pdata = NULL;  
 
    /* 2. 在队列末尾插入data1 */  
    struct _Data *data1 = (struct _Data *)calloc(1, sizeof(struct _Data));  
    data1->value = 1;  
    TAILQ_INSERT_TAIL(&head, data1, tailq_entry);  
    /* 3. 在队列末尾插入data2 */  
    struct _Data *data2 = (struct _Data *)calloc(1, sizeof(struct _Data));  
    data2->value = 2;  
    TAILQ_INSERT_TAIL(&head, data2, tailq_entry);  
    /* 4. 在data1之后插入data3 */  
    struct _Data *data3 = (struct _Data *)calloc(1, sizeof(struct _Data));  
    data3->value = 3;  
    TAILQ_INSERT_AFTER(&head, data1, data3, tailq_entry);  
    /* 5. 在data2之前插入data4 */  
    struct _Data *data4 = (struct _Data *)calloc(1, sizeof(struct _Data));  
    data4->value = 4;  
    TAILQ_INSERT_BEFORE(data2, data4, tailq_entry);  
    /* 6. 在队列首部插入data5 */  
    struct _Data *data5 = (struct _Data *)calloc(1, sizeof(struct _Data));  
    data5->value = 5;  
    TAILQ_INSERT_HEAD(&head, data5, tailq_entry);  
    /* 遍历队列 */  
    TAILQ_FOREACH(pdata, &head, tailq_entry) {  
        printf("pdata->value1 = %d\n", pdata->value);       
    }  
    puts("");  
    /* 7. 删除data5 */  
    TAILQ_REMOVE(&head, data5, tailq_entry);  
    free(data5);    /* TAILQ_REMOVE宏只是从队列中删除该节点,因此还需手动free */
 
    TAILQ_FOREACH(pdata, &head, tailq_entry) {  
        printf("pdata->value1 = %d\n", pdata->value);       
    }  
    puts("");  
 
    /* 正序遍历尾队列 */  
    /* 方法一 */  
    TAILQ_FOREACH(pdata, &head, tailq_entry) {  
        printf("pdata->value1 = %d\n", pdata->value);       
    }  
    puts("");  
    /* 方法二 */  
    for (pdata = TAILQ_FIRST(&head); pdata;   
                    pdata = TAILQ_NEXT(pdata, tailq_entry)) {  
        printf("pdata->value1 = %d\n", pdata->value);       
    }  
 
    puts("");  
 
    /* 逆序遍历尾队列 */  
    /* 方法一 */  
    TAILQ_FOREACH_REVERSE(pdata, &head, tailq_head, tailq_entry) {  
        printf("pdata->value1 = %d\n", pdata->value);       
    }  
    puts("");  
    /* 方法二 */  
    for (pdata = TAILQ_LAST(&head, tailq_head); pdata;   
            pdata = TAILQ_PREV(pdata, tailq_head, tailq_entry)) {  
        printf("pdata->value1 = %d\n", pdata->value);       
        TAILQ_REMOVE(&head, pdata, tailq_entry);  
        free(pdata);  
    }  
 
    if (TAILQ_EMPTY(&head)) {  
        printf("the tail queue is empty now.\n");     
    }  
 
    exit(EXIT_SUCCESS);  
}

代码github地址:https://github.com/astrotycoon/sys-queue.h

我们首先来看一下这个尾队列的定义:


注意,其中的tqe_prev指向的不是前一个元素,而是前一个元素中的tqe_next,这样定义的一个好处就是*tqe_prev就是自身的地址,**tqe_prev就是自身。

好,现在就顺着我的测试程序来一步步看如何使用这个尾队列吧!

第一步是初始化步骤。关于初始化我们有两种方法:使用宏TAILQ_HEAD_INITIALIZER或者使用宏TAILQ_INIT,这两者都是可以的,唯一的区别是传递给宏TAILQ_INIT的是地址,而传递给宏TAILQ_HEAD_INITIALIZER的不是,这点需要引起我们的注意。


初始化后的数据结构怎样的呢? 我们看下示意图:


接下来的两个步骤(步奏2和步奏3)都是在这个队列的尾部追加元素(data1和data2),使用的是宏TAILQ_INSERT_TAIL:


那么队列的变化过程是这样的,请看示意图:

接下来的操作是在data1之前插入data3,使用的是宏TAILQ_INSERT_AFTER:


形象的示意图如下:


整理后的示意图如下:


紧接着的操作是在data2之前插入data4,使用的是宏TAILQ_INSERT_BEFORE:


形象的示意图如下:


整理后的示意图如下:


现在在队列首部插入data5,使用的是宏TAILQ_INSERT_HEAD:


形象的示意图如下:


整理后的示意图如下:


删除数据data5使用是宏TAILQ_REMOVE:


现在的队列布局如下:


好了,基本的操作就这么多,接下来我们看看提供的几个数据元素访问方法:


前三个很简单,一看就懂,我们重点分析下TAILQ_LAST和TAILQ_PREV。

TAILQ_LAST的目的是获取队列中的最后一个元素的地址,注意是地址哦!(head)->tqh_last代表的是最后一个元素中tqe_next的地址,通过强转之后,((struct headname *)((head)->tqh_last))->tqh_last实际上就是最后一个元素中的tqe_prev,而文章一开始介绍定义的时候就说过,*tqe_prev代表的是自身元素的地址,所以TAILQ_LAST最后获取的就是最后一个元素的地址,宏TAILQ_PREV的道理是一样的。

OK,测试程序接下来就是遍历整个队列,并打印出数据,可以使用提供的宏TAILQ_FOREACH,也可以使用上述的几个访问方法来遍历。

好了,其实本文没啥内容,对我个人而言就主要是想熟悉下亿图这个软件,哈哈

sys/queue.h分析(图片复制不过来,查看原文)相关推荐

  1. sys/queue.h

    概述 sys/queue.h是LINUX/UNIX系统下面的一个标准头文件,用一系列的数据结构定义了一队列.包括singly-lined list, list, simple queue(Singly ...

  2. 网站防止盗链的方法总结(复制网页的时候,里面的图片复制不下来,就是别人用了防盗链的方法)...

    网站防止盗链的方法总结(复制网页的时候,里面的图片复制不下来,就是别人用了防盗链的方法) 一.总结 1.可以用 浏览器请求时HTTP头的Referer字段的值 复制网页的时候,里面的图片复制不下来,就 ...

  3. sys/socket.h

    http://fxr.watson.org/fxr/source/sys/socket.h 这个是不是内核里头的啊? 1 /*-2 * Copyright (c) 1982, 1985, 1986, ...

  4. co_routine.h分析

    co_routine.h #ifndef __CO_ROUTINE_H__ #define __CO_ROUTINE_H__#include <stdint.h> #include < ...

  5. iOS 多线程知识体系构建(三):GCD API(queue.h)解析篇

    Grand Central Dispatch (GCD) 是 Apple 开发的一个多核编程的较新的解决方法. Execute code concurrently on multicore hardw ...

  6. php分析图片水印,PHP开发的文字水印,缩略图,图片水印实现类与用法示例

    本文实例讲述了PHP开发的文字水印,缩略图,图片水印实现类与用法.分享给大家供大家参考,具体如下: 1.实现类ImageToTest.class.php参考代码 class ImageToTest { ...

  7. sys/cdefs.h: No such file or directory

    我在用neon加速时,引用了头文件"arm_neon.h" #include "arm_neon.h" 在qt项目配置文件加了 -mfloat-abi=soft ...

  8. Linux的目录结构和头文件相关;哪里找- sys/types.h, sys/stat.h

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_29757283/article/ ...

  9. c语言linux打印运行时间(耗时) gettimeofday()、timeval、<sys/time.h>

    #include <stdio.h> #include <sys/time.h>double __get_us(struct timeval t) { return (t.tv ...

最新文章

  1. Serverless的4种错误打开方式
  2. C#对事务的代码封装
  3. winform 时间控件 可以选择时分 设置为空
  4. qwidget多个窗口同步_【好人BUG】本机多组控制 一台电脑使用一个帐号登录多个(省钱) !...
  5. DNS resolving 占用大量日志
  6. java中使用es精准查询_使用ES简单查询语句须知
  7. java判断优先级代码_java运算符的优先级
  8. 二、ElasticSearch内置分词器
  9. 解决/usr/bin/ld: cannot find -lxxx
  10. linux安装mysql5.6rpm_centos6.5 下安装mysql5.6,rpm方式
  11. 第一颗国产HDMI 1.4 至 TTL / 2 端口 LVDS 芯片LT8619C
  12. 畅游陈德文:中国网游的发展与未来趋势
  13. 100M 免费 ASP + Access 空间 100M 免费 php+mysql 空间
  14. ElasticSearch实战(三十六)-Ingest Pipeline 多管道处理器
  15. MacM1下使用opencv
  16. 主板是2011针服务器型号,华硕服务器主板 Z9PA-D8/C 双路2011针脚
  17. 2022广东省安全员A证第三批(主要负责人)考试题库模拟考试平台操作
  18. 【三维激光扫描】第五章:基于点云数据的立面图绘制及三维建模
  19. insserv: Starting xx depends on plymouth and therefore on system facility `$all'
  20. oracle nbu异机恢复,通过NBU进行Oracle异机恢复的实验操作步骤

热门文章

  1. 程序员需要谨记的九大安全编码规则
  2. Jquery提交form表单
  3. poj3335 半平面交
  4. ORACLE10g R2及PATH官方下载地址
  5. automake linux,Linux下automake软件编译与发布快速入门
  6. 泉州经贸职业技术学院计算机系,部门简介-泉州经贸职业技术学院网络电教中心...
  7. python里orient_OrientDB Python连接操作
  8. java 插件开发 互相依赖_java – Eclipse插件开发:有没有办法控制有关我的插件缺少依赖项的安装程序消息?...
  9. duilib自定义消息
  10. python OSError: [Errno 24] Too many open files | HTTPConnectionPool(host=‘‘, port=80): Max retries e