这道题目的原型是
7-2 链表去重
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1 来表示。 (这句话很关键)
随后 N 行,每行按以下格式描述一个结点:
地址 键值 下一个结点
其中地址是该结点的地址,键值是绝对值不超过104的整数,下一个结点是下个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。
输入样例:
00100 5
99999 -7 87654
23854 -15 00000
87654 15 -1
00000 -15 99999
00100 21 23854
输出样例:
00100 21 23854
23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1
结尾无空行
**#include <bits/stdc++.h>
using namespace std;
struct node {
int date;
int next;
int add;
};
node a[100010]; //主要用到的数组也是数据存储的地方
int a1[100010],a2[100010]; //分离后的存储地址的数组,存储元素地址的数组;
int flag[100010]; //去重数组
int n,m,address,cnt1,cnt2,copy1;
void read() {
for (int i=0; i<n; i++) {
scanf("%d",&address);
scanf("%d%d",&a[address].date,&a[address].next);
a[address].add = address;
}
}
void check() {
for (int i=0; i<n; i++) {
if (m == -1){ //在这里我想了很久,做了很多次实验
//最终发现,其实这个模拟的链表可以不完整,可以在中间就断开了
//00010 2 00012
//00012 7 00033
//00033 6 -1
//99999 8 66666
//66666 9 22222
这种情况挺致命的,所以要在这里判断掉,其余的就是中规中矩的写法了;
break;
}
if (flag[abs(a[m].date)] != 0) {
a2[cnt2++] = a[m].add;
} else {
flag[abs(a[m].date)] = 1;
a1[cnt1++] = a[m].add;
}
m = a[m].next;
}
}
void display() {
printf("%05d %d ",a1[0],a[a1[0]].date);
for (int i=1; i<cnt1; i++) {
printf("%05d\n",a1[i]);
printf("%05d %d ",a1[i],a[a1[i]].date);
}
printf("-1\n");
//这里面存在一个特判,要是没有分离出来,就是全部都不相同的情况就特殊考虑一下;
if (cnt2) {
printf("%05d %d ",a2[0],a[a2[0]].date);
for (int i=1; i<cnt2; i++) {
printf("%05d\n",a2[i]);
printf("%05d %d ",a2[i],a[a2[i]].date);
}
printf("-1\n");
}
}
int main() {
scanf("%d%d",&m,&n);
copy1 = m;
read();
check();
display();
return 0;
}**