L2-002 链表去重 (25 分)
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
输入格式:
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤10
5
,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 −1 来表示。
随后 N 行,每行按以下格式描述一个结点:
地址 键值 下一个结点
其中地址是该结点的地址,键值是绝对值不超过10
4
的整数,下一个结点是下个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。
输入样例:
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 <stdio.h>
#include <string.h>
#include <math.h>
#define N 10*10*10*10*10+1
struct Node
{
int jian,xia; //jian→键位、xia→下一个结点
}node[N];
int main()
{
int l,n; //l→首个地址,n→有几个地址、输入几轮
int first; //每一轮的起始地址
int i,j; //用于循环和数组下标
int tmp[10001]={0};
//配合循环拆分链表时,检验这个下标是否出现过,若出现则赋值给被删除的链表
int one[N],two[N];
// one → 表示去重后的链表,two → 表示被删除的链表
int o=0,t=0;
int num; //num得到每一个地址的键值
scanf("%d%d",&l,&n);
for(i=0;i<n;i++)
{
scanf("%d",&first);
scanf("%d%d",&node[first].jian,&node[first].xia);
}
for(i=l;node[i].xia != -1;)
{
int num=abs(node[i].jian);
if(tmp[num]==0)
{
tmp[num]=1;
one[o++]=i; //存储地址
}
else
{
two[t++]=i;
}
i=node[i].xia;
}
num=abs(node[i].jian);//这里要注意一下最后一个下标
if(tmp[num]==0)
{ one[o++]=i;}
else
{ two[t++]=i;}
printf("%05d %d ",one[0],node[one[0]].jian);
for(j=1;j<o;j++)
{
printf("%05d\n",one[j]);
printf("%05d %d ",one[j],node[one[j]].jian);
}
printf("%d\n",-1);
if(t!=0) //没删除过链表的情况需要判断一下
{
printf("%05d %d ",two[0],node[two[0]].jian);
for(j=1;j<t;j++)
{
printf("%05d\n",two[j]);
printf("%05d %d ",two[j],node[two[j]].jian);
}
printf("%d\n",-1);
}
return 0;
}