实现有序递增链表的归并,直接使用原序列中的结点,返回归并后的带头结点的链表头指针。
首先要对链表的插入删除非常熟悉,这样才容易实现。下面是我对归并过程画的草图
首先需要判断两个序列的第一个数大小,保存较小的数的头结点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;
}