02-线性结构1 两个有序链表序列的合并 (15 分)
本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个非递减的整数序列。
函数接口定义:
List Merge( List L1, List L2 );
其中List结构定义如下:
typedef struct Node PtrToNode;
struct Node {
ElementType Data; / 存储结点数据 /
PtrToNode Next; / 指向下一个结点的指针 /
};
typedef PtrToNode List; / 定义单链表类型 */
L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和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;
}
/* 你的代码将被嵌在这里 */
输入样例:
3
1 3 5
5
2 4 6 8 10
输出样例:
1 2 3 4 5 6 8 10
NULL
NULL
分析
- 题目简单,但读题不仔细,刚开始想用之前头节点直接当新的头,没考虑到输出L1 L2
- 提交有问题一直说Node没有定义, 索性直接把所有的函数都具体实现一边,跑完没有问题。
代码
#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;
}
List Read(){
int num;
scanf("%d", &num);
List L = (List)malloc(sizeof( Node));
L->Next = NULL;
List tail;
tail = L;
for (int i = 0; i < num; ++i)
{
int data;
scanf("%d", &data);
List pNode = (List)malloc(sizeof(Node));
pNode -> Data = data;
tail -> Next = pNode;
tail = pNode;
}
tail -> Next = NULL;
return L;
}
void Print(List L){
List pNode = L->Next;
if (pNode == NULL){
printf("NULL\n");
return;
}
while(pNode != NULL){
printf("%d ", pNode->Data);
pNode = pNode->Next;
}
printf("\n");
}
List Merge( List L1, List L2 )
{
List L3=(List)malloc(sizeof(Node));
List L=L3;
List p=L1->Next;
List q=L2->Next;
while(p&&q)
{
if(p->Data<q->Data)
{
L->Next=p;
p=p->Next;
}
else
{
L->Next=q;
q=q->Next;
}
L=L->Next;
}
L->Next=p ? p : q;
L1->Next=NULL;
L2->Next=NULL;
return L3;
}
类似题目:链表重排(25 分)
Problem Description
给定一条单链表,将链表结点进行头尾交错重新排序,即如果一条单链表为 L1 -> L2 -> … -> L(n-1) -> Ln ,那么重新排序完的结果是 L1 -> Ln -> L2 -> L(n-1) -> L3 -> L(n-2) -> …
Input
每个输入文件中一组数据。
第一行给出结点的总个数N(0<N<10^5)和单链表的第一个结点的地址。所有结点的地址要么是一个五位正整数,要么是用-1表示的空地址NULL。然后是N行,表示N个结点,每行的格式为
Address Data Next
其中Address为结点地址(不足5位的高位用零填充至5位),Data为结点的数据域(绝对值不超过10^5的整数),Next为结点的指针域(即下一个结点的地址)。数据保证Address不等于-1。
Output
输出按题目要求重新排序后的单链表。第一行为重新排序后单链表上结点的个数、第一个结点的地址。
之后每行一个结点,输出格式与输入相同,结点输出顺序为单链表连接顺序。
Sample Input
5 11111
33333 0 44444
22222 2 33333
11111 5 22222
05689 8 -1
44444 6 05689
Sample Output
5 11111
11111 5 05689
05689 8 22222
22222 2 44444
44444 6 33333
33333 0 -1
Address: https://logn.me/problem/1042
Note1
- 思路有些清奇,以为int型装不下,用的字符串 。正排一边 , 正序逆序记录两次,交替输出前一半。 ——超时
Code1
#include<iostream>
#include<cstring>
using namespace std;
#define MAX 100100
struct Node{
char address[7];
int data;
char next[7];
}a[MAX], sort1[MAX], sort2[MAX];
int main(){
int num;
char temp[7], start[7];
scanf("%d %s", &num, start);
for(int i = 0; i < num; i++){
scanf("%s %d %s", a[i].address, &a[i].data, a[i].next);
}
int cnt = 0;
strcpy(temp, start);
int i;
while(cnt < num){
for(i = 0; strcmp(a[i].address, temp) != 0; i++);
sort1[cnt++] = a[i];
sort2[num - cnt] = a[i];
strcpy(temp , a[i].next);
}
if(num % 2 == 0) strcpy(sort1[num/2 + 1].address, "-1");
else strcpy(sort2[num/2].address, "-1");
printf("%d %s\n", num, start);
for(i = 0; i <= num/2; i++){
printf("%s %d %s\n", sort1[i].address, sort1[i].data, sort2[i].address);
if(!(num % 2 == 1 && i == num / 2))
printf("%s %d %s\n", sort2[i].address, sort2[i].data, sort1[i + 1].address );
}
}
Note2
- 用int型存储,利用地址直接哈希, 排序完后记录会去
- const int maxn = 1e5 + 10 值得借鉴的用法
Code2
#include<iostream>
#include<string>
using namespace std;
const int maxn=1e5+10;
struct Node{
int ad,next,data;
}a[maxn],ans[maxn];
int main(){
int ptr,num,address;
scanf("%d %d",&num, &ptr );
for(int i = 0; i < num; i++) {
scanf("%d", &address);
scanf("%d %d", &a[address].data, &a[address].next);
}
int cnt=1;
printf("%d %05d\n", num, ptr);
while(ptr != -1){
ans[cnt].ad = ptr;
ans[cnt++].data = a[ptr].data;
ptr = a[ptr].next;
}
for(int i = 1; i < cnt ; i++){
if(i%2 == 0)
a[i] = ans[cnt - i/2];
else
a[i] = ans[i/2 + 1];
}
for(int i = 1; i < cnt-1; i++){
printf("%05d %d %05d\n",a[i].ad, a[i].data, a[i+1].ad);
}
printf("%05d %d -1\n", a[cnt-1].ad, a[cnt-1].data);
return 0;
}