链表去重PTA【厦大数据结构第一次上机】

1.2 链表去重

给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。

输入格式:
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤10 为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1 来表示。

随后 N 行,每行按以下格式描述一个结点:
地址 键值 下一个结点

其中地址是该结点的地址,键值是绝对值不超过10 的整数,下一个结点是下个结点的地址。

输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。

输入样例:

99999 -7 87654
23854 -15 00000
87654 15 -1
00000 -15 99999
00100 21 23854

输出样例:

23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1

笔者提示:
核心思想是用数组模拟内存空间,“可视化”内存空间。
难点1:
题目给出的地址如何处理。
难点2:
将原链表去重容易,但是将去重后的新链表重新串起难,将删除的链表,以原顺序输出难

解决方案

num[k]:存储地址为k的结点的值
back[k]:存储地址为k的结点的后继地址
res1[0],res1[1],res1[2]....:新链表第一个结点的地址,新链表第二个结点的地址,新链表第三个结点的地址

Step1.遍历原链表,用isRepeat数组记录,结点元素的绝对值是否出现过,若未出现,赋值为1
Step2.赋值为1的同时,将第一次出现的绝对值,其原结点对应的地址存入res1数组(res1数组存储新链表的结点地址)。否则,将重复出现的绝对值,其原结点对应的地址存入res2数组。待遍历结束,链表结点的分组也完成
Step3.如何按顺序输出新链表?将res1数组的下标,天然提供了一个线性的顺序。
如:要输出res1[0]对应的结点A:A地址–res1[0],A值–num[res1[0]],A的下一结点地址:res[1]
利用数组自带的属性,就能巧妙解决问题
参考代码

#include<stdio.h>
#include<math.h>
const int N = 1e5 + 5;
int res1[N], res2[N]; //res1存储新序列结点地址,res2存储删除序列
int num[N], back[N]; //num存储值,back存储下一地址
bool isRepeat[N];//默认值为false
int main() {
	int head, n, t;
	scanf("%d%d", &head, &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &t);
		scanf("%d%d", &num[t], &back[t]);
	}

	int i = head, l1 = 0, l2 = 0;
	while (back[i] != -1) {
		if (isRepeat[abs(num[i])] == false) { //若未出现过
			isRepeat[abs(num[i])] = true;
			res1[l1++] = i;
		} else
			res2[l2++] = i;
		i = back[i]; //索引到下一地址
	}

	if (isRepeat[abs(num[i])] == false) { //处理最后一个
		isRepeat[abs(num[i])] = true;
		res1[l1++] = i;
	} else
		res2[l2++] = i;
		
	//输出新序列
	if (l1) { //若l1不为0
		for (int i = 0; i < l1 - 1; i++) {
			printf("%05d %d %05d\n", res1[i], num[res1[i]], res1[i + 1]);
		}
		printf("%05d %d -1\n", res1[l1 - 1], num[res1[l1 - 1]]);
	}
	
	//输出被删除序列
	if (l2) { //若l2不为0
		for (int i = 0; i < l2 - 1; i++) {
			printf("%05d %d %05d\n", res2[i], num[res2[i]], res2[i + 1]);
		}
		printf("%05d %d -1", res2[l2 - 1], num[res2[l2 - 1]]);
	}
	return 0;
}

运行结果
在这里插入图片描述
在此感谢我滴舍友,jy同学~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

快苏排序OAO

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

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

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

打赏作者

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

抵扣说明:

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

余额充值