通用双向链表的设计(参考Linux系统中的实现)
通常我们设计设计链表都是将数据域放在里面,这样每次需要使用链表的时候都需要实现一个链表,然后重新实现它的相关操作,这里参考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系统中的实现)的更多相关文章
- 常见linux系统中RPM包的通用命名规则
本文重点说一下在常见的linux系统中,RPM包通用的命名规则. RPM包的一般格式为:name-version-arch.rpmname-version-arch.src.rpm 例:httpd-2 ...
- (转)浅谈 Linux 系统中的 SNMP Trap
原文:https://www.ibm.com/developerworks/cn/linux/l-cn-snmp/index.html 简介 本文讲解 SNMP Trap,在介绍 Trap 概念之前, ...
- 在linux系统中安装VSCode(Visual Studio Code)
在linux系统中安装VSCode(Visual Studio Code) 1.从官网下载压缩包(话说下载下来解压就直接可以运行了咧,都不需要make) 访问Visual Studio Code官网 ...
- 用户管理 之 在Linux系统中,批量添加用户的操作流程
一.阅读此文件您需要掌握的基础知识: <Linux 用户(user)和用户组(group)管理概述><用户(user)和用户组(group)配置文件详解><Linux 用 ...
- 用户管理 之 Linux 系统中的超级权限的控制
在Linux操作系统中,root的权限是最高的,也被称为超级权限的拥有者.普通用户无法执行的操作,root用户都能完成,所以也被称之为超级管理用户. 在系统中,每个文件.目录和进程,都归属于某一个用户 ...
- 获得Unix/Linux系统中的IP、MAC地址等信息
获得Unix/Linux系统中的IP.MAC地址等信息 中高级 | 2010-07-13 16:03 | 分类:①C语言. Unix/Linux. 网络编程 ②手册 | 4,471 次阅读 ...
- 理解Linux系统中的load average(图文版)转
一.什么是load average? linux系统中的Load对当前CPU工作量的度量 (WikiPedia: the system load is a measure of the amount ...
- Linux系统中常见文件系统格式
Windows常用的分区格式有三种,分别是FAT16.FAT32.NTFS格式. 在Linux操作系统里有Ext2.Ext3.Linux swap和VFAT四种格式. FAT16: 作为一种文件名称, ...
- Linux系统中存储设备的两种表示方法
转:https://blog.csdn.net/holybin/article/details/38637381 一.对于IDE接口的硬盘的两种表示方法: 1.IDE接口硬盘,对于整块硬盘的两种表示方 ...
随机推荐
- 数组全排列 knuth 分解质因数
template<typename T> void swap(T* a, T* b) { T temp = *a; *a = *b; *b = temp; } //数组的全排列 void ...
- Java多线程之~~~ReadWriteLock 读写分离的多线程实现
在多线程开发中,常常会出现一种情况,我们希望读写分离. 就是对于读取这个动作来说,能够同一时候有多个线程同 时去读取这个资源,可是对于写这个动作来说,仅仅能同一时候有一个线程来操作.并且同一时候,当有 ...
- chardet的使用
http://blog.csdn.net/jy692405180/article/details/52496599
- 使用 rman duplicate from active database 搭建dataguard 手记--系列二
run { allocate channel prmy1 type disk; allocate channel prmy2 type disk; allocate channel prmy3 typ ...
- python(8)- python基础数据类型
数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视 频.网页等各种各样的数据,不同的数据,需要 ...
- VS2010配置QT5.5.0开发环境
一.官网下载QT和qtvsaddin插件 网址:http://www.qt.io/download-open-source/ 1. 2. 3. 得到下载的安装包,点击安装就能够了 watermark/ ...
- Selenium学习(二)入门小例子
1)打开百度页面 2)输入“hello” 3)点击百度一下按钮 from selenium import webdriver url = "http://" + "www ...
- Python Journey
1. 开发环境搭建 - Eclipse + PyDev搭建开发环境: http://www.cnblogs.com/Bonker/p/3584707.html (其实,如果不是License限制,推荐 ...
- 在JS中将JSON的字符串解析成JSON数据格式
使用eval函数来解析 <script> var data="{root: [{name:'1',value:'0'},{name:'6101',value:'北京市'},{na ...
- 2018.11.23-day26 面向对象(终结)
1.私有成员不能被继承2.装饰器方法--(类方法&静态方法)3.装饰器--property方法4.反射