理解Linux双向链表

理解Linux双向链表


原文:

http://blog.csdn.net/leisure512/article/details/5188986

我截取其中一部分,并加了图解。


Linux内核中双向链表hlist_head,它的定义:

struct hlist_head {
struct hlist_node *first;

};


struct hlist_node {
struct hlist_node *next, **pprev;

};


显然,这个双向链表不是真正的双向链表,因为表头只有一个first域,为什么这样设计?代码中的注释解释:为了节约内存,特别适合作为Hash表的冲突链,但Hash表很大时,那么表头节约下来的内存就相当客观了,虽然每个表头只节约一个指针。


同时,表头的不一致性也会带来链表操作上的困难,显然就是在表头和首数据节点之间插入节点时需要特别处理,这也就是为什么会设计二级指针pprev的原因。看看代码

static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
{
n->pprev=next->pprev;
n->next=next;
next->pprev=&n->next;
*(n->pprev)=n;
}


解释:指针n指向新节点,指针next指向将要在它之前插入新节点的那个节点。

看上面的代码,就可以看到二级指针pprev的威力了!有没有看到,当next就是第一个数据节点时,这里的插入也就是在表头和首数据节点之间插入一个节点,但是并不需要特别处理!而是统一使用*(n->pprev)来访问前驱的指针域(在普通节点中是next,而在表头中是first)。这太经典了!


我详细解释下面的代码:

static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
{
n->pprev=next->pprev; 1
n->next=next; 2
next->pprev=&n->next; 3
*(
n->pprev)=n; 4
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值