数据结构——有序递增链表的归并

实现有序递增链表的归并,直接使用原序列中的结点,返回归并后的带头结点的链表头指针。

首先要对链表的插入删除非常熟悉,这样才容易实现。下面是我对归并过程画的草图

首先需要判断两个序列的第一个数大小,保存较小的数的头结点P1。然后将P2中小于或等于P1当前结点与下一结点数据范围内的序列短插入到P1中,直到P1或者P2指向NULL。实现过程不难,但是要熟悉链表的操作。下面是实现这一过程的函数部分源程序:

List Merge( List L1, List L2 )
{
	/*
	**	P1 第一个数据小的链表的头结点,P2 较大的头结点
	**	S1 P1链表尾结点,S2 P2链表尾结点
	*/ 
	List P1,P2,t,P,S1,S2;
	P = (List)malloc(sizeof(struct Node));
	
	if(L1->Next == NULL && L2->Next == NULL)	/* L1 L2 均为 NULL */ 
	{
		P->Next = NULL;
		return P;
	}
	if(L1->Next == NULL)						/* L1 为 NULL */ 
	{
		P->Next = L2->Next;
		L2->Next = NULL;
		return P;
	}
	if(L2->Next == NULL)						/* L2 为 NULL */
	{
		P->Next = L1->Next;
		L1->Next = NULL;
		return P;
	}
	
	if(L1->Next->Data < L2->Next->Data)
	{
		P1 = L1;
		P2 = L2;
	}
	else
	{
		P1 = L2;
		P2 = L1;
	}
	t = P1;				/* 建立连接 */ 
	
	S1 = P1->Next;
	S2 = P2->Next; 

	for (P2 = P2->Next; S1!=NULL && P2!=NULL; )
	{
		while(P1->Next != NULL && P1->Next->Data < P2->Data )		/* P1遍历到小于或等于P2的结点 */
			P1 = P1->Next;
	//	printf("P1->Data=%d,P2->Data=%d\n", P1->Data,P2->Data);	
		S1 = P1->Next;								
		S2 = P2; 
		if(S1 == NULL)	break; 
		while(S2->Next != NULL && S2->Next->Data <= S1->Data)
			S2 = S2->Next;
	//	printf("S1->Data=%d,S2->Data=%d\n", S1->Data,S2->Data);		
		/* 
		** 将P2链表部分插入到P1
		** 如 P1中3->7 需要插入P2 3->4->5 
		*/
		P1->Next = P2;
		P2 = S2->Next; 
		S2->Next = S1;	 
		P1 = S1;
	//	Print(P);
	}	

	if( S1 == NULL )	/* P1的尾数小于P2 */ 
		P1->Next = P2;
	
	P->Next = t->Next;
	L1->Next = NULL;	
	L2->Next = NULL;
	
	return P;
}

注意:链表为空的情况,同时要防止错误使用NULL指针的情况。

源程序(输入与输出)

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
    ElementType Data;
    PtrToNode   Next;
};
typedef PtrToNode List;

List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表;空链表将输出NULL */

List Merge( List L1, List L2 );

int main()
{
    List L1, L2, L;
    while(getchar()!=EOF)
    {
    	L1 = Read();
   	    L2 = Read();
	    L = Merge(L1, L2);
    Print(L);
    Print(L1);
    Print(L2);
	}
    return 0;
}

List Read() /* 细节在此不表 */
{
	List P,L,t;
	int n,i;
	L = (List)malloc(sizeof(struct Node));
	P = L; 
	scanf("%d",&n);
	for( i=0; i<n; i++)
	{
		t = P;
		P = (List)malloc(sizeof(struct Node));
		scanf("%d",&P->Data);
		t->Next = P;
	}
	P->Next = NULL;
	return L;
}

void Print( List L ) /* 细节在此不表;空链表将输出NULL */
{
	List P=L->Next;
	for(; P != NULL; P = P->Next)
		printf("%d ", P->Data);
	if(L->Next == NULL)
		printf("NULL");
	printf("\n");
}
/* 你的代码将被嵌在这里 */
List Merge( List L1, List L2 )
{
	/*
	**	P1 第一个数据小的链表的头结点,P2 较大的头结点
	**	S1 P1链表尾结点,S2 P2链表尾结点
	*/ 
	List P1,P2,t,P,S1,S2;
	P = (List)malloc(sizeof(struct Node));
	
	if(L1->Next == NULL && L2->Next == NULL)	/* L1 L2 均为 NULL */ 
	{
		P->Next = NULL;
		return P;
	}
	if(L1->Next == NULL)						/* L1 为 NULL */ 
	{
		P->Next = L2->Next;
		L2->Next = NULL;
		return P;
	}
	if(L2->Next == NULL)						/* L2 为 NULL */
	{
		P->Next = L1->Next;
		L1->Next = NULL;
		return P;
	}
	
	if(L1->Next->Data < L2->Next->Data)
	{
		P1 = L1;
		P2 = L2;
	}
	else
	{
		P1 = L2;
		P2 = L1;
	}
	t = P1;				/* 建立连接 */ 
	
	S1 = P1->Next;
	S2 = P2->Next; 

	for (P2 = P2->Next; S1!=NULL && P2!=NULL; )
	{
		while(P1->Next != NULL && P1->Next->Data < P2->Data )		/* P1遍历到小于或等于P2的结点 */
			P1 = P1->Next;
	//	printf("P1->Data=%d,P2->Data=%d\n", P1->Data,P2->Data);	
		S1 = P1->Next;								
		S2 = P2; 
		if(S1 == NULL)	break; 
		while(S2->Next != NULL && S2->Next->Data <= S1->Data)
			S2 = S2->Next;
	//	printf("S1->Data=%d,S2->Data=%d\n", S1->Data,S2->Data);		
		/* 
		** 将P2链表部分插入到P1
		** 如 P1中3->7 需要插入P2 3->4->5 
		*/
		P1->Next = P2;
		P2 = S2->Next; 
		S2->Next = S1;	 
		P1 = S1;
	//	Print(P);
	}	

	if( S1 == NULL )	/* P1的尾数小于P2 */ 
		P1->Next = P2;
	
	P->Next = t->Next;
	L1->Next = NULL;	
	L2->Next = NULL;
	
	return P;
}

猜你喜欢

转载自blog.csdn.net/Bridge3/article/details/82528306