pat basic 1105 链表合并

给定两个单链表 L1​=a1​→a2​→⋯→an−1​→an​ 和 L2​=b1​→b2​→⋯→bm−1​→bm​。如果 n≥2m,你的任务是将比较短的那个链表逆序,然后将之并入比较长的那个链表,得到一个形如 a1​→a2​→bm​→a3​→a4​→bm−1​⋯ 的结果。例如给定两个链表分别为 6→7 和 1→2→3→4→5,你应该输出 1→2→7→3→4→6→5。

输入格式:

输入首先在第一行中给出两个链表 L1​ 和 L2​ 的头结点的地址,以及正整数
N (≤105),即给定的结点总数。一个结点的地址是一个 5 位数的非负整数,空地址 NULL 用 -1 表示。

随后 N 行,每行按以下格式给出一个结点的信息:

Address Data Next

其中 Address 是结点的地址,Data 是不超过 105 的正整数,Next 是下一个结点的地址。题目保证没有空链表,并且较长的链表至少是较短链表的两倍长。

输出格式:

按顺序输出结果链表,每个结点占一行,格式与输入相同。

输入样例:

00100 01000 7
02233 2 34891
00100 6 00001
34891 3 10086
01000 1 02233
00033 5 -1
10086 4 00033
00001 7 -1

输出样例:

01000 1 02233
02233 2 00001
00001 7 34891
34891 3 10086
10086 4 00100
00100 6 00033
00033 5 -1

解题思路:

唉……翻了好多次车,全都在merge函数里。现在回过头看翻车的原因也不复杂,两个链表有一个走完了之后及时结束合并就可以了。还好其他部分比较顺利,总算是完成了。

#include <stdio.h>
#include <stdlib.h>
#define MAXN 100000

typedef struct node *PtrN;
struct node {
	int address, data, link;
	PtrN next;
};
typedef PtrN List;
typedef enum { false, true } bool;

int GetLength(List l) {
	int cnt;
	for ( cnt=0; l; ++cnt, l=l->next);
	return cnt;
}

List Reverse(List l) {
	if ( !l || !l->next ) return l;
	PtrN p1, p2, p3;
	p1 = l; p2 = l->next; p3 = p2->next;
	p1->next = NULL;
	p1->link = -1;
	while ( p3 ) {
		p2->next = p1;
		p2->link = p1->address;
		p1 = p2; p2 = p3; p3 = p3->next;
	}
	p2->next = p1;
	p2->link = p1->address;
	l = p1 = NULL; /* 内存清零 */

	return p2;
}

/* 在p的后面插入node */
bool AfterInsert(PtrN p, PtrN node) {
	if ( p && node ) {
		node->next = p->next;
		node->link = p->link;
		p->next = node;
		p->link = node->address;
		return true;
	} else {
		return false;
	}
}

/* 合并链表,b是短的那个 */
void Merge(List a, List b) {
	PtrN pa1, pa2, pb1, pb2;
	pa1 = pa2 = a; pb2 = b;
	while ( pa2 && pa2->next ) {
		pa1 = pa2->next;
		pa2 = pa1->next;
		pb1 = pb2;
		pb2 = pb2->next;
		if ( !AfterInsert(pa1, pb1) || !pb2 )
			break;
	}
}

List BuildList(int head, int temp[][MAXN]) {
	if ( head == -1 ) return NULL;
	List l, p, tmp;
	l = (List)malloc(sizeof(struct node));
	l->address = head;
	l->data = temp[0][head];
	l->link = temp[1][head];
	p = l;
	while ( p->link != -1 ) {
		tmp = (List)malloc(sizeof(struct node));
		tmp->address = p->link;
		tmp->data = temp[0][tmp->address];
		tmp->link = temp[1][tmp->address];
		p->next = tmp;
		p = p->next;
	}
	p->next = NULL;

	return l;
}

void PrintList(List l) {
	if ( !l ) return;
	while ( l->next ) {
		printf("%05d %d %05d\n", l->address, l->data, l->link);
		l = l->next;
	}
	printf("%05d %d -1\n", l->address, l->data);
}

int main(int argc, const char *argv[]) {
	int N, h1, h2, addr, data, link, length1, length2;
	int temp[2][MAXN];

	if ( scanf("%d %d %d", &h1, &h2, &N)==EOF ) printf("error\n");
	while ( N-- ) {
		if ( scanf("%d %d %d", &addr, &data, &link)==EOF ) printf("error\n");
		temp[0][addr] = data;
		temp[1][addr] = link;
	}
	List l1 = BuildList(h1, temp);
	List l2 = BuildList(h2, temp);
	length1 = GetLength(l1);
	length2 = GetLength(l2);
	if ( length1 >= length2 * 2 ) {
		l2 = Reverse(l2);
		Merge(l1, l2);
		PrintList(l1);
	} else if ( length1 * 2 <= length2 ) {
		l1 = Reverse(l1);
		Merge(l2, l1);
		PrintList(l2);
	}

	return EXIT_SUCCESS;
}

猜你喜欢

转载自blog.csdn.net/herbertyellow/article/details/126821564