2.3.2笔记-归并有序链表

                                             教材《数据结构》第31页继续讨论如何将两个有序链表并为一个有序链表

        假设头指针为La和Lb的单链表分别为线性表LA和LB的存储结构,现要归并La和Lb得到单链表Lc,之前已经在2.2笔记线性表合并中提到过合并(算法2.7(P26)),相同点都是要La和Lb是有序链表,然后判断pa->data<=pb->data时,则将pa所指结点链接到pc所指结点之后,否则将pb所指结点链接到pc所指结点之后。同时下面程序用到的算法2.12(P31)的时间复杂度和算法2.7相同。

        两个算法(算法2.7和算法2.12)不同之处在于空间复杂度不同。下面的程序在归并两个链表为一个链表时,不需要另建立新表的结点空间,而只需将原来两个链表中结点之间的关系解除,重新按元素值非递减的关系将所有结点链接成一个链表。

下面的源代码涉及到了算法2.11(P30)和算法2.12(P31)。算法2.11逆序建立带表头结点的单链表,算法2.12是归并有序的La和Lb为新的有序单链表Lc。


//algo2-3.cpp实现算法2.11和算法2.12的程
#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
struct LNode{
	ElemType data;
	LNode *next;
};
typedef LNode * LinkList;//定义LinkList为LNode型指针
void CreateList1(LinkList &L,int n){
//正位序(结点插在表尾)输入n个元素的值,建立带表头结点的单链线性表L
	int i;
	LinkList p,q;
	L=(LinkList)malloc(sizeof(LNode));//生成头结点
	L->next=NULL;//先建立一个带头结点的空单链表
	q=L;//q指向空表的头结点(相当于尾结点)
	printf("请输入%d个数据\n",n);
	for(i=1;i<=n;i++)
	{
		p=(LinkList)malloc(sizeof(LNode));
		scanf("%d",&p->data);//给新结点输入元素值
		q->next=p;//将新结点插在表尾
		q=q->next;//q指向尾结点,亦即p和q指向同一个结点
	}
	p->next=NULL;//最后一个结点的指针指针域为空
}
void CreateList(LinkList &L,int n){//算法2.11
//逆位序(结点插在表头)输入n个元素的值,建立带表头结点的单链线性表L
	int i;
	LinkList p;
	L=(LinkList)malloc(sizeof(LNode));//生成头结点
	L->next=NULL;//先建立一个带头结点的空单链表
	printf("请输入%d个数据\n",n);
	for(i=n;i>0;--i)
	{
		p=(LinkList)malloc(sizeof(LNode));//生成新结点
		scanf("%d",&p->data);//给新结点输入元素值
		p->next=L->next;//将新结点插在表头
		L->next=p;//头结点指向新结点
	}
}
void print(ElemType e){
printf("%d ",e);
}
void ListTraverse(LinkList L,void (*visit)(ElemType )){
	//初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数visit()
	LinkList p=L->next;
	while(p)//p所指结点存在
	{
		visit(p->data);//对p所指结点调用函数visit()
		p=p->next;//p指向下一个结点
	}
	printf("\n");
}
void MergeList(LinkList La,LinkList &Lb,LinkList &Lc){//算法2.12
	//已知单链线性表La和Lb的元素按值非递减排列
	//归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列(销毁Lb,Lc即新的La)
	LinkList pa=La->next,pb=Lb->next,pc;//pa,pb分别指向La,Lb的首元结点(待比较结点)
	Lc=pc=La;//用La的头结点作为Lc的头结点,pc指向La的头结点(Lc的尾结点)
	while(pa&&pb){//La和Lb中的元素都未比较完
		if(pa->data<=pb->data)//La的当前元素不大于Lb的当前元素
		{
			pc->next=pa;//将pa所指结点归并到Lc中
			pc=pa;//pc指向表Lc的最后一个结点
			pa=pa->next;//表La的下一个结点成为待比较结点
		}else//Lb的当前元素小于La的当前元素
		{
			pc->next=pb;//将pb所指结点归并到Lc中
			pc=pb;//pc指向表Lc的最后一个结点
			pb=pb->next;//表Lb的下一个结点成为待比较结点
		}
		
	}
	pc->next=pa?pa:pb;//插入剩余段
	free(Lb);//释放Lb的头结点
	Lb=NULL;//Lb不再指向任何结点


}
void main(){
	int n=5;
	LinkList La,Lb,Lc;
	printf("按非递减排序");
	CreateList1(La,n);//根据输入顺序,正无序建立线性表
	printf("La=");
	ListTraverse(La,print);//输出链表La的内容
	printf("按非递增排序");
	CreateList(Lb,n);//根据输入顺序,逆位序建立线性表
	printf("Lb=");
	ListTraverse(Lb,print);//输出链表Lb的内容
	MergeList(La,Lb,Lc);//按非递减顺序归并La和Lb,得到新表Lc
	printf("Lc=");
	ListTraverse(Lc,print);//输出链表Lc的内容

}
结果图:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值