6.6.6 链表的合成
如果需要对链表进行合成操作,那么在list.h中又是如何实现的呢?接下来看看用于链表合成操作的函数__list_splice()的代码。
static inline void__list_splice(struct list_head*list,
struct list_head*head)
{
struct list_head*first=list->next;
struct list_head*last=list->prev;
struct list_head*at=head->next;
first->prev=head;
head->next=first;
last->next=at;
at->prev=last;
}
该函数的功能是将一个链表插入到另外一个链表中,不做链表是否为空的检查。调用该函数进行合成操作的时候,对于链表是否为空的检测需要在调用该函数之前进行。因为每个链表只有一个头结点,将空链表插入到另外一个链表中是没有意义的,而被插入的链表可以为空。当然,也可以采用下面的函数先对链表进行是否为空的检测,再对其进行合成操作。
static inline void list_splice(struct list_headlist,struct list_headhead)
{
if(!list_empty(list))
__list_splice(list,head);
}
在以上链表的合成操作中会丢弃list所指向的头结点,因为两个链表各有一个头结点,所以必须删除其中一个头结点。只要list是非空链,head无任何限制,list_splice()就能实现链表的合并。如果需要使用丢弃的链表头来创建另外一个链表,那么可以使用下面的函数来实现。
static inline void list_splice_init(struct list_head*list,
struct list_head*head)
{
if(!list_empty(list)){
__list_splice(list,head);
INIT_LIST_HEAD(list);
}
}
这个函数的功能是将一个链表list的有效信息合并到另外一个链表head之后,重新初始化被丢弃的空链表头。对于以上实现链表合成操作函数,同样通过下面的一段代码来看具体的使用方法。
include<stdio.h>
include<stdlib.h>
include"list.h"
typedef struct_stu
{
char name[20];
int num;
struct list_head list;
}stu;
int main()
{
stupstu,pstu2;
stu*tmp_stu;
struct list_head stu_list,stu_list2;
struct list_head*pos;
int i=0;
INIT_LIST_HEAD(&stu_list);
INIT_LIST_HEAD(&stu_list2);
pstu=malloc(sizeof(stu)*3);
pstu2=malloc(sizeof(stu)*3);
for(i=0;i<3;i++)
{
sprintf(pstu[i].name,"Stu%d",i+1);
sprintf(pstu2[i].name,"Stu%d",i+4);
pstu[i].num=i+1;
pstu2[i].num=i+4;
list_add(&(pstu[i].list),&stu_list);
list_add(&(pstu2[i].list),&stu_list2);
}
printf("stu_list链表\n");
list_for_each(pos,&stu_list)
{
tmp_stu=list_entry(pos,stu,list);
printf("student num:%d\tstudent name:%s\n",tmp_stu->num,tmp_stu->name);
}
printf("stu_list2链表\n");
list_for_each(pos,&stu_list2)
{
tmp_stu=list_entry(pos,stu,list);
printf("student num:%d\tstudent name:%s\n",tmp_stu->num,tmp_stu->name);
}
printf("stu_list链表和stu_list2链表合并以后\n");
list_splice(&stu_list2,&stu_list);
list_for_each(pos,&stu_list)
{
tmp_stu=list_entry(pos,stu,list);
printf("student num:%d\tstudent name:%s\n",tmp_stu->num,tmp_stu->name);
}
free(pstu);
return 0;
}
运行结果:
root@ubuntu:/home/paixu/dlist_node#./a
stu_list链表
student num:3 student name:Stu3
student num:2 student name:Stu2
student num:1 student name:Stu1
stu_list2链表
student num:6 student name:Stu6
student num:5 student name:Stu5
student num:4 student name:Stu4
stu_list链表和stu_list2链表合并以后
student num:6 student name:Stu6
student num:5 student name:Stu5
student num:4 student name:Stu4
student num:3 student name:Stu3
student num:2 student name:Stu2
student num:1 student name:Stu1