数据结构-02-线性结构1 两个有序链表序列的合并 (15 分)

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

分析

  1. 题目简单,但读题不仔细,刚开始想用之前头节点直接当新的头,没考虑到输出L1 L2
  2. 提交有问题一直说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

  1. 思路有些清奇,以为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

  1. 用int型存储,利用地址直接哈希, 排序完后记录会去
  2. 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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值