Pat Basic 1105 リンク リスト マージ

2 つの単一リンクリスト L1 =a1 →a2 →⋯→an−1 →an と L2 =b1 →b2 →⋯→bm-1 →bm が与えられるとします。n ≥ 2m の場合、あなたのタスクは、短いリンク リストの順序を逆にして、それを長いリンク リストにマージして、a1 →a2 →bm →a3 →a4 →bm の形式のリンクを取得することです。 1 ⋯ 結果。たとえば、2 つのリンクされたリスト 6→7 と 1→2→3→4→5 がある場合、1→2→7→3→4→6→5 を出力する必要があります。

入力形式:

入力はまず、最初の行で 2 つのリンク リスト L1 および L2 のヘッド ノードのアドレスと、正の整数
N (≤105)、つまり指定されたノードの総数を指定します。ノードのアドレスは 5 桁の非負の整数であり、空のアドレス NULL は-1で表されます。

次に N 行があり、各行には次の形式でノードの情報が表示されます。

Address Data Next

ここでAddress、 はノードのアドレス、Dataは 105 を超えない正の整数、Nextは次のノードのアドレスです。この問題により、空のリンク リストが存在せず、長いリンク リストが短いリンク リストの少なくとも 2 倍の長さになることが保証されます。

出力フォーマット:

入力と同じ形式で、各ノードが 1 行を占める結果リストを順番に出力します。

入力例:

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

問題解決のアイデア:

ため息... たくさんの間違いを経験しましたが、それらはすべてマージ関数にあります。今振り返ってみると、ひっくり返った理由は複雑ではなく、2 つのリンク リストのいずれかが完了した時点でマージを終了すれば十分です。幸い他の部分は順調に進み、ようやく完成しました。

#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