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;
}