问题描述
给定一个键值为整数的单链表 L,将键值的绝对值有重复的结点删除:即对任意键值 K,只 有键值或其绝对值等于 K 的第一个结点被保留在 L 中。例如,下面单链表 L 包含键值 21、 -15、15、7、-15,去重后的链表 L 包含键值 21、-15、7。
输入说明
输入的第一行包含两个整数,分别表示链表第一个结点的地址和结点个n(1≤n≤100)。结 点地址是一个非负的 5 位整数,NULL 指针用-1 表示。 随后 n 行,每行含 3 个整数,按下列格式给出一个结点的信息: Address Key Next 其中 Address 是结点的地址,Key 是绝对值不超过 10000 的整数,Next 是下一个结点的地址。
输出说明
输出的第一行为去重后链表 L 的长度,换行;接下来按顺序输出 L 的所有结点,每个结点 占一行,按照 Address Key Next 的格式输出,间隔 1 个空格。
测试样例
输入样例 1
00100 5
99999 7 87654
23854 -15 00000
87654 -15 -1
00000 15 99999
00100 21 23854
输出样例
1
300100 21 23854
23854 -15 99999
99999 7 -1
解题思路
这道题看似是一道链表题,但是我是拿结构体和数组做的哈哈哈,当时是想着拿adress做数组的下标,结果虽然做出来了但感觉程序稍微有些笨重。
首先建立了一个结构体,flag的作用主要是为了去重,开始时flag都置为1,每遇到一组数组,拿它和剩下各组数据的data值比较,如果与剩下的数据中data绝对值相等,则剩下的那个数据flag设为0,表示重复了。
struct LNode{
int adress;
int data;
int next;
int flag;//flag作为标志 如果数据绝对值相同,且不是第一次遇到则为0。
}table[100000],newtable[100];
建立两个结构体数组,第一个是乱序也就是按输入的顺序存在,数组下标为自己的adress值,第二个中的数据是按指针排列后的数据,数组下标为0,1,2~n-1。
然后通过一个for循环给第一个数组赋值,再通过一直for循环将第一个数组的数据整理后赋给newtable数组,此时newtable数组存放的数据是按链表顺序,之后通过一个双重for循环逐一排查重复的元素,并将其flag置为0,计算去重后链表的长度count,然后重新更新非重元素的后继节点的地址。
输出:如果不是最后一个数据,则正常输出,如果是最后一个数据,则注意要把它的next数据域置为-1. //注意:因为int类型的原因,adress输入有前缀0的时候系统会消掉前缀0,所以最后输出的时候要根据位数补足前缀0.因为此题要求adress和next为5位数,所以用到了一个巧妙地方法:输出时为 %05d ,这样系统会自动让这个将要被输出的数变成5位数,缺位数的时候往前补前缀0.
完整代码
#include <stdio.h>
#include<malloc.h>
struct LNode{
int adress;
int data;
int next;
int flag;//flag作为标志 如果数据绝对值相同,且不是第一次遇到则为0。
}table[100000],newtable[100];
int main()
{
int num,n,i,site,count=0,t;
scanf("%d %d",&num,&n);
for(i=0;i<n;i++)
{
scanf("%d",&site);//输入地址
scanf("%d %d",&table[site].data,&table[site].next);
table[site].adress=site;//用地址做下标
table[site].flag=1;//flag均置为1
}
int j;
j=num;
for(i=0;i<n;i++)
{
newtable[i]=table[j];//整理数组,使之按链表顺序排列
j=table[j].next;
}
for(i=0;i<n;i++)//去重(使重复元素flag置为0)
{
for(j=i+1;j<n;j++)
{
if((newtable[j].data==newtable[i].data||newtable[j].data==-1*(newtable[i].data))&&newtable[j].flag==1)
{
newtable[j].flag=0;
}
}
}
for(i=0;i<n;i++)
{
if(newtable[i].flag!=0)
{
count++;//计算去重后链表长度
}
for(j=i+1;j<n;j++)
{
if(newtable[j].flag==0)
continue;
if(newtable[j].flag==1)
{
newtable[i].next=newtable[j].adress;//更新去重后的next数据域
break;
}
}
}
printf("%d\n",count);
for(i=0,t=0;i<n;i++)
{
if(newtable[i].flag!=0)
{
t++;
if(t<count)//看是否为最后一个输出
{
printf("%05d %d %05d\n",newtable[i].adress,newtable[i].data,newtable[i].next);
}
if(count==t)
{
printf("%05d %d",newtable[i].adress,newtable[i].data);
printf(" -1");//最后一个输出next值为-1
printf("\n");
}
}
}
return 0;
}