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;
}