PAT甲级 1052 Linked List Sorting (25分)

该博客主要解析PAT甲级编程题1052,涉及链表排序和处理无效节点的问题。博主分析了题目要求,指出原始链表节点的key值排序可以通过静态链表实现,并提供了错误代码的原因和解决方案,即添加bool变量flag记录节点有效性,对有效节点进行输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1052 Linked List Sorting (25分)

题目链接:PAT A 1052
在这里插入图片描述
题目大意:这道题要求对给定的每个链表组成结构(即节点)按照key值从小到大排序,输出排序后链表的节点个数,头结点,以及链表中的每个结构。

思路分析:PAT里的链表题地址基本都是由五六位的数字构成,非常清晰直观,因此我们可以使用静态链表来解决。所谓静态链表,就是结构体里的next变量不再是指针类型,而是整型变量,例如a的地址是11111,b的地址是22222,那么node[11111].next = 22222,就可以用来表示a->b。这道题中我们直接写一个sort函数对key值进行排序,排序完成后每个节点的地址address,key值都是不变的,唯一需要改变的就是该节点的下一个节点的地址next。写一个for循环,对于每个节点,将该节点(v[i])下一个节点的地址赋值为v[i+1].address,当i=n-1的时候(即最后一个节点),v[i].next赋值为-1,最后按照顺序输出即可。需要注意的是,输出是按照%05d的格式进行输出的,因为输入00001,计算机会自动认为是1,故输出时需要补足零,而且对于最后一个节点的next地址应输出-1,而不是-00001,这都是需要特别考虑的。

错误代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct node{
	int address, key, next;
};
bool cmp(node a, node b) {
	return a.key < b.key;
}
int main() {
	int n, head;
	scanf("%d %d", &n, &head);
	vector<node> v(n);
	for(int i = 0; i < n; i++) 
		scanf("%d %d %d", &v[i].address, &v[i].key, &v[i].next);
	sort(v.begin(), v.end(), cmp);
	printf("%d %05d\n", n, v[0].address);
	for(int i = 0; i < n - 1; i++) 
		v[i].next = v[i + 1].address;
	v[n - 1].next = -1;
	for(int i = 0; i < n - 1; i++) 
		printf("%05d %d %05d\n", v[i].address, v[i].key, v[i].next);
	printf("%05d %d %d\n", v[n - 1].address, v[n - 1].key, v[n - 1].next);
	return 0;
}

这份代码提交上去得分是21/25,那么错在哪了呢?

原来题目中暗含了一个坑,就是有的节点可能是无效节点,也就是说个别节点可能根本不在题目给出的首地址开始的链表上,就是出来凑数的!!!而且还存在均为无效结点的情况,这种情况也需要特判输出。我们需要在结构体中增加一个bool变量flag,用来判断该节点是否在链表上,初始时所有节点flag均为false。然后从头节点开始遍历该链表,如果节点在链表上,flag为true。之后进行结构体排序,把flag为false的节点都排到后面去,只针对flag为true的节点进行输出即可~

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;
struct Node{
	int address, key, next;
	bool flag; //判断是否为无效节点 
}node[100010];
bool cmp(Node a, Node b) {
	if(a.flag == false || b.flag == false) //只要a和b中有一个无效节点,就把它排到后面去 
		return a.flag > b.flag;
	else //按键值大小排序 
		return a.key < b.key;
}
int main() {
	for(int i = 0; i < 100010; i++) //初始时均赋值为无效节点 
		node[i].flag = false;
	int n, head, address;
	scanf("%d %d", &n, &head);
	for(int i = 0; i < n; i++) {
		scanf("%d", &address);
		scanf("%d %d", &node[address].key, &node[address].next);
		node[address].address = address;
	}
	int p = head, count = 0;
	while(p != -1) { //统计有效节点 
		node[p].flag = true;
		p = node[p].next;
		count++; //有效节点个数加一 
	}
	if(count == 0) //全部是无效节点,特判输出 
		printf("0 -1");
	else {
		sort(node, node + 100010, cmp); //排序 
		printf("%d %05d\n", count, node[0].address); //注意%05d格式输出 
		for(int i = 0; i < count - 1; i++) 
			printf("%05d %d %05d\n", node[i].address, node[i].key, node[i + 1].address);
		printf("%05d %d -1", node[count - 1].address, node[count - 1].key); //最后一个节点的next为-1 
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值