数据结构:通用链表

linux/list.h

linux内核中使用的链表
特点是可以复用,无需反复造轮子.
容易想到的一种链表用法是这样的:
struct list{
    strucu list *next, *prev;
    int priv_data;
};
数据被储存在链表的节点内部 通过next和prev移动来访问各个节点上的priv_data.
这样做的问题在于代码几乎没有复用性,不同的数据存储就需要对应的多种list.

而linux kernel中提出了一种数据包含在节点之外的链表 能很好的解决这个问题.
struct list_head {
    struct list_head *prev, *next;
};

struct list_data {
    struct list_head head;
    int priv_data;
};
数据结构体list_data只需要包含一个链表结构list_head 就可以使用链表的特性.

list_entry

侵入式的链表添加节点 删除节点的功能都不难实现.
难点在于如何简便的遍历链表,这就有赖于list_entry宏
#define list_entry(ptr,type,member) \
    ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
这个宏看上去比较复杂 但实际上可以简化下增加可读性
    ptr - &((type *)0)->member
ptr是指向struct head的指针,type是节点结构struct data的数据类型,而member则是struct head类型的变量在struct data中的变量名.

   所以list_entry宏实质上就是用 指向struct head变量的指针减去struct head变量和数据结构起始地址的偏移量 = 数据结构起始地址.

遍历链表

1. list_for_each(pos,head)
遍历链表的节点的head pos和head都是struct head类型指针
2. list_for_each_entry(pos,head,member)
遍历链表的节点 pos是链表节点类型指针 head是struct head类型指针 memberstruct head变量在节点类型中的变量名
3. list_for_each_entry_safe(pos,n,head,member)
和list_for_each_entry类似 多了一个节点类型指针n用来保障访问安全
一般用在删除链表某个节点

参考实现

其实就是linux kernel里的通用list 我自己试着实现了一遍 摘取了部分我认为比较常用的功能.
https://github.com/sliver-chen/codingutil/tree/master/data_struct/List
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值