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