深入浅出linux内核源代码之双向链表list_head(下)
来源:互联网 发布:2016淘宝网购数据分析 编辑:程序博客网 时间:2024/05/30 23:33
原创文章,转载请注明出处,谢谢!
作者:清林,博客名:飞空静渡
我用一个程序来说明在structperson中增加了structlist_head变量后怎么来操作这样的双向链表。
编译:
linux下的可以:gcc -g -Wall main.c -otest
windows下的可以建一个控制台工程,把main.c和list.h加到工程中编译。
运行test后的输出如下:
===========print the list ===============
age:35, weight: 60
age:30, weight: 55
age:25, weight: 50
age:20, weight: 45
age:15, weight: 40
age:10, weight: 35
==========print list after delete a node which age is 20 ==========
age:35, weight: 60
age:30, weight: 55
age:25, weight: 50
age:15, weight: 40
age:10, weight: 35
我们看到,这就是一个非常好和有效的双向链表,我们不需要为每一种结构去定义相关的函数,如遍历、增加和删除等函数,我们只需要简单的在结构中增加structlist_head的一个变量,我们的结构立马就变成了一个双向链表,而且,我们对链表的操作也不用自己写,直接调用已经定义好的函数和宏,一切就那么简单和有效。
文章写到这里是不是应该结束了呢,没有,我还不想结束,还想在继续说。
四、一个结构多个链表
在上面,我们看到人的结构是这样的:
structperson
{
intage;
intweight;
structlist_head list;
};
它的链表图形看起来如下图所示:
但我们知道,一个人,他的熟悉还有很多,例如他有各种各样的衣服,各种不同的鞋子等。所以,我定义了两个这样的结构:
structclothes
{
int size; //衣服有各种大小
Colorcolor; //衣服有各种颜色,这里假设有一种Color的类型
};
structshoot
{
Kind kind; // 鞋子有各种类型,秋、冬、运动、休闲等,同样假设已经定义过Kind这样的类型
Colorcolor; // 鞋子也有各种颜色
};
那么这个人的定义可能就是这样的:
structperson
{
intage;
intweight;
structclothes clo;
structshoot sht;
};
在这里,我有意clo和sht这两个变量放在list后面,其实,代表链表的list在结构中的位置在哪里是没什么关系的,list_entry也一样可以将结构的指针找出来。
这里有一个问题是,一个人不止一件衣服,也不止一双鞋子,所以我们应该把他拥有的衣服和鞋子应该加上,那么怎么加呢?这里应该把衣服和鞋子的结构也变成链表,这不就解决了。
把结构改一下,变成了这样:
structclothes
{
structlist_head list;
int size; //衣服有各种大小
Colorcolor; //衣服有各种颜色,这里假设有一种Color的类型
};
structshoot
{
structlist_head list;
Kind kind; // 鞋子有各种类型,秋、冬、运动、休闲等,同样假设已经定义过Kind这样的类型
Colorcolor; // 鞋子也有各种颜色
};
现在鞋子和衣服都是链表了,都可以把它们连接起来。那我们的结构是不是还应该这样定义:
structperson
{
intage;
intweight;
structclothes clo;
structshoot sht;
};
如果是,那么我们应该怎么定义这个头节点。在前面我们看到,定义一个person_head的头节点是这样的:
//定义并初始化一个链表头
structperson person_head;
INIT_LIST_HEAD(&person_head.list);
难道我们应该这样定义吗?
//定义并初始化一个链表头
structperson person_head;
INIT_LIST_HEAD(&person_head.list);
INIT_LIST_HEAD(&person_head.col.list);
INIT_LIST_HEAD(&person_head.sht.list);
那么增加一件衣服进去呢,代码看起来是这样的:
structclothes tmp =(struct clothes*)malloc(sizeof(struct clothes));
…...
list_add(&(tmp->list),&(person_head.clo.list));
这样会不会有点麻烦,其实,如果我们可以认真想一想,我们会发现,既然structperon是一个含有list_head的结构,它可以把它的类型节点链接在后面,那么structclothes也是一个含有list_head的结构,它们本质也没什么区别,应该也可以链接在它后面的。所以我们的structperson的结构应该变成这样:
structperson
{
intage;
intweight;
structlist_head clo;
structlist_head sht;
};
那么我们链接节点后的图形如下图所示:
<!--@page { margin: 2cm }P { margin-bottom: 0.21cm }-->
由上面,我们可以知道,有了structlist_head结构,我们可以为我们的结构体增加多个子节点链表。
这篇文章的pdf版和代码可以在下面的连接上下载:
深入浅出linux内核源代码之双向链表list_head.zip
- 深入浅出linux内核源代码之双向链表list_head(下)
- 深入浅出linux内核源代码之双向链表list_head(下)
- 深入浅出linux内核源代码之双向链表list_head(下)
- 深入浅出linux内核源代码之双向链表list_head(下)
- 深入浅出linux内核源代码之双向链表list_head(下):
- 深入浅出linux内核源代码之双向链表list_head(上)
- 深入浅出linux内核源代码之双向链表list_head(上)
- 深入浅出linux内核源代码之双向链表list_head(上)
- 深入浅出linux内核源代码之双向链表list_head(上)
- 深入浅出linux内核源代码之双向链表list_head(上)
- 深入浅出linux内核源代码之双向链表list_head(上)
- 深入浅出linux内核源代码之双向链表list_head(上)
- 深入浅出linux内核源代码之双向链表list_head(上)
- linux 内核分析之list_head 双向链表结构
- linux内核数据结构之双向循环链表struct list_head
- linux内核源码“双向链表list_head”
- linux内核源码“双向链表list_head”续
- (Linux 内核)双向循环链表list_head
- php中一个不太完美的字符串编码判断函数
- 什么是Web Service
- php原生API vs. PDO vs. Zend Db效率对比
- 认识自己
- 腾讯啊,你为什么那么拽?
- 深入浅出linux内核源代码之双向链表list_head(下)
- 闭包
- Python编码规范
- IBM试图重新定义资产管理
- Python的内存管理
- utf8字符串截取
- 你最后悔什么?
- Android APK 反编译
- http中不可靠的Accept-Encoding