题意:
给出N个结点的地址address、数据域data以及指针域next,然后给出链表的首地址,要
求把在这个链表上的结点按data值从小到大输出。
样例解释:
按照输入,这条链表是这样的(结点格式为[address, data, next]):
[00001, 0, 22222]→[22222, 1000, 12345]→[12345, -1, 33333]→[33333, 100000, 11111]→[11111,100, -1]
按key值排序之后得到:
[12345, -1, 00001]→[00001, 0, 11111]→[11111, 100, 22222]→[22222, 1000, 33333]→[33333,100000, -11
此处可以直接套用前面讲解的一般解题步骤。
步骤1:定义静态链表,其中结点性质由bool型变量flag定义,表示为结点在链表中是
否出现。flag为false表示无效结点(不在链表上的结点)。
步骤2:初始化,令flag均为false(即0),表示初始状态下所有结点都是无效结点。
步骤3:由题目给出的链表首地址begin遍历整条链表,并标记有效结点的flag为true(即1),同时计数有效结点的个数count。
步骤4:对结点进行排序,排序函数cmp的排序原则是:如果cmp的两个参数结点中有无效结点的话。则 按flag大到小排序,以把有效结点排到数组左端(因为有效结点的flag为1,大于无效结点的flag),否则按数据域从小到大排序(第二级条件)。
步骤5:由于有效结点已经按照数据域从小到大排序,因此按要求输出有效结点即可.
注意点
1.可以直接使用 % 05d的输出格式,以在不足五位时在高位补0。但是要注意 - 1不能使用 % 05d输出,否则会输出 - 0001(而不是 - 1或者 - 00001),因此必须要留意 - 1的输出。
2.题目可能会有无效结点,即不在题目给出的首地址开始的链表上。
3.数据里面还有均为无效的情况,这时就要根据有效结点的个数特判输出”0 - 1”。
#include<iostream> #include<algorithm> using namespace std; const int maxn = 100005; struct Node { int data; int next; int address; bool flag;//判断节点是否在链表上。 }node[maxn]; bool cmp(Node a, Node b) { if (a.flag == 0 || b.flag == 0) { return a.flag > b.flag; } else { return a.data < b.data; } } int main() { for (int i = 0; i < maxn; i++) {//初始化 node[i].flag = false; } int n, s, address; scanf("%d%d", &n, &s); for (int i = 0; i < n; i++) { scanf("%d", &address); scanf("%d%d", &node[address].data, &node[address].next); node[address].address = address; } int count = 0,p = s; while (p !=-1) { node[p].flag = true;//进行标记 count++;//记录有效节点的个数。 p = node[p].next; } if (count == 0) { printf("0 -1"); } else { sort(node, node + maxn, cmp); printf("%d %05d\n", count, node[0].address);//先输出链表元素个数,再输出第一个节点的位置 for (int i = 0; i < count; i++) { if (i != count - 1) { printf("%05d %d %05d\n",node[i].address, node[i].data, node[i + 1].address);//第三个位置是下一个元素的地址 } else {//如果是最后一个元素则将其下一个节点的位置输出为“-1”,防止-1被%05d化。 printf("%05d %d -1\n", node[i].address, node[i].data); } } } return 0; }