输入样例:
3
1 3 5
5
2 4 6 8 10
函数接口定义:
List Merge( List L1, List L2 );
裁判测试程序样例:
#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;
}
/* 你的代码将被嵌在这里 */
输出样例:
1 2 3 4 5 6 8 10
NULL
NULL
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
List Merge( List L1, List L2 ){
List P,Q,S,tail;// S为新有序链表,P和Q分别为L1和L2当前扫描的结点,tail是新有序链表的尾结点
P=L1->Next,Q=L2->Next;//由于L1和L2是带头结点的单链表,所以L1->Next为链表的第一个结点
S=(List)malloc(sizeof(struct Node));//申请一个新结点空间
tail=S;//尾指针指向这个新结点,因为返回的链表也是带头结点的,所以这个新的结点作为最终链表的头结点
//当P和Q其中一个为NULL时,循环结束
while(P!=NULL&&Q!=NULL){
//比较大小
if(P->Data<Q->Data){
tail->Next=P;//将小的直接插入在链表尾部
tail=P;//尾指针后移
P=P->Next;//插入之后,P向后移动
}
//Q->Next<=P->Next时
else{
tail->Next=Q;//将小的直接插入在链表尾部
tail=Q;//尾指针后移
Q=Q->Next;//插入之后,Q向后移动
}
}
tail->Next=P?P:Q;//P和Q谁不为NULL,谁就把剩下的部分直接链接到tail后面
L1->Next=NULL; // 将L1和L2的头结点的Next指针设为NULL
L2->Next=NULL;
return S;//返回最终链表的头结点
}
上述代码中,为什么要将L1和L2的头结点的Next指针设为NULL?
将L1和L2的头结点的Next指针设为NULL,使得合并后的新链表的结尾指向NULL,避免出现错误的next指针指向。如果不清空头结点的Next指针,可能会导致合并后的新链表结尾部分指向L1和L2中原有的结点,从而产生意料之外的结果。
此外,合并链表后,L1和L2已经不再合法,因为它们各自的链表结构已经被改变,如果后续还要对它们进行操作,有可能会产生未知的副作用。因此,为了避免不必要的错误,将它们的头结点Next指针设为NULL是一个好的习惯。
其中List结构定义如下:
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。
文章为作者独立观点,不代表股票交易接口观点