两个有序链表序列的合并(C语言版 + 注释)

本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个非递减的整数序列。

函数接口定义:

List Merge( List L1, List L2 );

其中List结构定义如下:

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */

L1L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。

裁判测试程序样例:

#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;
    L1 = Read();
    L2 = Read();
    L = Merge(L1, L2);
    Print(L);
    Print(L1);
    Print(L2);
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

3
1 3 5
5
2 4 6 8 10

输出样例:

1 2 3 4 5 6 8 10 
NULL
NULL

代码:

#include <stdio.h>
#include <stdlib.h>    //malloc()函数在其中。

typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
    ElementType Data;    //存储结点数据。
    PtrToNode   Next;    //指向下一个结点的指针。
};
typedef PtrToNode List;    //定义单链表类型。

List Read();    //读入单链表的函数。
void Print( List L );    //打印单链表的函数。
List Merge( List L1, List L2 );    //合并非递减单链表函数。

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

List Read() {
	int N, i;
	scanf("%d", &N);    //读入表长。
	
	List L = (List)malloc(sizeof(struct Node));    //申请头结点 L.
	L->Next = NULL;    //将头结点置空。
	List r = L;    //要用尾插法构建链表,r是尾指针。
	for ( i = 0; i < N; i++ ) {
		List p = (List)malloc(sizeof(struct Node));    //申请新结点空间p.
		scanf("%d", &p->Data);    //给p的数据域赋值。
		r->Next = p;    //将p串进链表中。
		r = p;    //此时p变成了最后一个结点,尾指针指向p.
	}
	r->Next = NULL;    //最后一个结点要指向NULL.
	
	return L;    //读入完成,返回链表L。
}

void Print( List L ) {
	List p = L->Next;    //将p指向第一个结点,L是头结点,它的下一个结点才是第一个结点。
	if ( p ) {    //链表非空。
		List r = L;    //建立一个临时指针r,指向L.
		while ( r->Next ) {    //当r是最后一个结点的时候,r->Next刚好是NULL退出循环。
			r = r->Next;    //每轮更新r.
			printf("%d ", r->Data);    //打印当前结点的数据域。
		}
	} 
	else	printf("NULL");    //链表为空,直接输出NULL.
	printf("\n");
}

List Merge( List L1, List L2 ) {
	List pa, pb, pc, L;
	L = (List)malloc(sizeof(struct Node));    //申请一个头结点L.
	pa = L1->Next;    //指针pa指向L1的第一个结点。
	pb = L2->Next;    //指针pb指向L2的第一个结点。
	pc = L;    //指针pc指向上面创立的头结点L.
	while ( pa && pb ) {    //当L1和L2链表都没有遍历完成的时候。
		if ( pa->Data <= pb->Data ) {    //若pa结点的数据小。
			pc->Next = pa;    //把pa串入L中。
			pc = pa;    //pc移向当前最后一个结点pa,这也是尾插。
			pa = pa->Next;    //在L1链表中,更新pa位置。
		} else {
			pc->Next = pb;
			pc = pb;
			pb = pb->Next;
		}
	}
    /*如果L1未遍历完,将L1全部串入L,如果L2未遍历完,将L2全部串入L*/
	pc->Next = pa ? pa : pb;
	L1->Next = NULL;
	L2->Next = NULL;
	
	return L;
} 

猜你喜欢

转载自blog.csdn.net/YelloJesse/article/details/82556771