通常我们设计设计链表都是将数据域放在里面,这样每次需要使用链表的时候都需要实现一个链表,然后重新实现它的相关操作,这里参考Linux系统中的设计实现了一个通用的双向链表,只需要在你的结构里面有一个这个链表的域,就可以使用链表的相关操作了。

注意:这个通用的双向链表是参考Linux系统中的实现,它使用了typeof这个功能,所以有些编译器可能不支持。我是再Windows系统中使用MinGW下使用GCC编译的。

// list.h

#ifndef _list_h
#define _list_h
typedef struct _list_head {
    struct _list_head *prev,*next;
} list_head;
#define offsetof(TYPE,MEMBER) ( (size_t) &((TYPE*)0)->MEMBER )
#define container_of(ptr,type,member) ({\
    const typeof( ((type*)0)->member ) *__mptr = (ptr);\
    (type*)( (char*)__mptr - offsetof(type,member) );})
#define list_empty(head) ( head->next==0&&head->prev==0 )
/* get the member of list object
 * @ptr        pointer to list_head
 * @type    the type of container which contains list_head field
 * @memeber field name in the container
 * @return    return pointer to the container
 */
#define list_entry(ptr,type,member) container_of(ptr,type,member)
/* add a new node after `head`
 */
void list_add(list_head *head,list_head *node);
/* delete a node
 */
void list_del(list_head *node);
#endif

/

// list.c

#include "list.h"
/* add a new node after `head`
 */
void list_add(list_head *head,list_head *node) {
    if(list_empty(head)) {
        head->next = head;
        head->prev = head;
    }
    node->next = head->next;
    node->prev = head;
    head->next->prev = node;
    head->next = node;
}
/* delete a node
 */
void list_del(list_head *node) {
    node->prev->next = node->next;
    node->next->prev = node->prev;
}

///

// test.c

#include <stdio.h>
#include <assert.h>
#include "list.h"
typedef struct _task {
    int id;
    list_head next;
} task;
#define task_next(t) ( container_of(t->next.next,task,next) )
void task_print(task *t) {
    printf("#%d -> ",t->id);
}
void task_foreach(task *head,void (*callback)(task *)) {
    task *p = head;
    do {
        callback(p);
        p = task_next(p);
    }
    while (p!=head);
}
// use task like a list
void test_list() {
    task t1={1,{0,0}},
        t2={2,{0,0}},
        t3={3,{0,0}},
        t4={4,{0,0}},
        t5={5,{0,0}};
    list_add(&t1.next,&t2.next);
    list_add(&t2.next,&t3.next);
    list_add(&t3.next,&t4.next);
    list_add(&t4.next,&t5.next);
    task_foreach(&t1,task_print);
}
int main(int argc, char *argv[]) {
    test_list();
    return 0;
}

编译运行

    gcc test.c list.h list.c -o test
    .\test.exe

下载代码

通用双向链表的设计(参考Linux系统中的实现)相关推荐

  1. linux无密码sudo,在Linux系统中运行没有sudo密码的特定命令

    本文介绍在Linux操作系统中运行没有sudo密码的特定命令的方法. 背景 我在AWS上部署了Ubuntu系统上的脚本,此脚本的主要目的是检查特定服务是否以固定间隔运行(确切地说每隔一分钟),并且如果 ...

  2. Linux系统中提示/usr/bin/ld: cannot find -lxxx错误的通用解决方法

    Linux系统中提示/usr/bin/ld: cannot find -lxxx错误的通用解决方法 参考文章: (1)Linux系统中提示/usr/bin/ld: cannot find -lxxx错 ...

  3. Linux系统自动备份脚本,供参考的Linux系统中自动执行分段备份脚本

    供参考的Linux系统中自动执行分段备份脚本 发布时间:2014-04-21 15:49:00来源:红联作者:tioced 以下脚本仅做学习参考,需加到/etc/crontab文件,每天执行一次的脚本 ...

  4. 如何在Linux系统中安装DBeaver通用数据库工具

    DBeaver是一个开源.功能齐全.跨平台的通用数据库管理工具和SQL客户端,可在Linux操作系统.Windows和macOS 系统上运行. DBeaver支持80多个数据库管理系统,包括Postg ...

  5. linux动态库ppt,LINUX系统中动态链接库创建与使用补充_区块链白皮书代写|市场计划书项目PPT设计_Tbleg...

    区块链白皮书代写 大家都知道,在WINDOWS系统中有很多动态链接库(以.DLL为后缀文件,DLL即Dynamic Link Library).这种动态链接库,和静态函数库不同,它里面函数并不是执行程 ...

  6. 浅谈 Linux 系统中的 SNMP Trap 【转】

    文章来源:浅谈 Linux 系统中的 SNMP Trap 简介 本文讲解 SNMP Trap,在介绍 Trap 概念之前,首先认识一下 SNMP 吧. 简单网络管理协议(Simple Network ...

  7. Linux 系统中的 SNMP Trap

    简介 本文讲解 SNMP Trap,在介绍 Trap 概念之前,首先认识一下 SNMP 吧. 简单网络管理协议(Simple Network Management Protocol)是一种应用层协议, ...

  8. Linux 系统中的 SNMP Trap及常用OID

    浅谈 Linux 系统中的 SNMP Trap 转载: http://www.ibm.com/developerworks/cn/linux/l-cn-snmp/ 本文讲解 SNMP Trap,在介绍 ...

  9. linux查找最近访问的文件,教您在Linux系统中查找最近修改的文件/文件夹

    如果您使用Linux系统进行日常操作,则主目录文件将随时间急剧增加.如果您有成千上万个文件,很可能不记得最近更改的文件名,本文将教您在Linux系统中查找最近修改的文件/文件夹.另外,如果要检查出于任 ...

最新文章

  1. qtablewidget限制输入类型_对敏感型电子信号输入实施过压保护的可靠新方法
  2. 计算价格, java中浮点数精度丢失的解决方案
  3. python下载代码-python下载大文件代码
  4. SQL Server 2005中创建CLR存储过程
  5. 架构漫谈:我心中的架构
  6. 关于Server Tomcat v8.0 Server at localhost failed to start的解决办法
  7. NeurIPS 2021 | 图上不均衡表示学习新视野:基于拓扑结构的不均衡学习
  8. 直播 | AAAI 2021最佳论文:比Transformer更有效的长时间序列预测
  9. java对嵌入式_Java用于嵌入式系统的优点
  10. 【抓包工具】HttpWatch(功能详细介绍)
  11. Blocking/Non-Blocking VS Sync/Async VS Overlapped
  12. Oracle最新的Java 8更新破坏了您的工具-它是如何发生的?
  13. 全文搜索Apache Lucene简介
  14. web开发项目,web前端CSS全局样式,面试必问
  15. MFC遍历指定目录下的所有文件/文件夹(不遍历子目录)
  16. UIViewController生命周期的理解
  17. kafka是什么_Kafka的Controller Broker是什么
  18. python建模 决策_决策树python建模中的坑 :ValueError: Expected 2D array, got 1D array instead:...
  19. mysql 数据脱敏
  20. c语言怎么用右移代替除法,除法和算术右移之间的巧妙取代

热门文章

  1. linux shell中21的含义
  2. 本题主要考查指针与数组
  3. Silverlight+WCF 实战-网络象棋最终篇之对战视频-下篇[客户端发送与服务端中转](六)...
  4. Design Pattern: Singleton 模式
  5. Android碎片化难题:手游兼容性测试应该适配哪些机型?
  6. SVN关于忽略xcuserdata目录
  7. 隐藏Apache Nginx PHP版本号
  8. AFNetworking 下载文件断点续传操作
  9. Config Sharepoint 2013 Workflow PowerShell Cmdlet
  10. android异步任务详解 AsynTask[转 杨瓦瓦]