XDOJ 258 链表去重

问题描述

给定一个键值为整数的单链表 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;
}


  • 16
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一——一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值