提要
题目就不说了,这是一道甲乙级皆有的PAT练习题,只是语言不同。
注意点:是“每K个节点”反转一次,而不是前K个节点,本人之前一直没有理解,导致一直有两个测试点过不去…
还有就是并非每个节点都算有效,就导致有可能K>N的情况出现,需要另外处理,我相信看到我这篇的同学基本应该都知道这些。
思路
这里很多题友给出的思路是老老实实按题目反转,涉及前后替换地址啊什么的,从教程角度来说比较复杂,我根本看不懂(直球。
于是我最后想到了一种很容易理解的方法,大部分都在代码里以注释的方式说明了,这里也解释一下:
1、首先用vector存储初始顺序的链表:比如例题里给出的123456
2、把反转的部分直接用reverse函数解决(),当然这个时候只有数据是符合输出顺序的,而地址还是乱的:比如例题里给出的123456现在在vector里变成了432156,但是每个数据对应的next节点地址都是原来的,也就是错误的。
3、为了把地址搞定,直接从vector的头节点开始循环给每个节点的next地址赋值为它的下一个节点的地址即可
总而言之这样做的好处就是不用在反转的过程中不需要考虑next节点的问题,只要到后面解决即可,非常的方便,非常的美味。
#include<iostream>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<cstring>
#include<math.h>
using namespace std;
struct node
{
int address;
int data;
int next;
}r[100005];
int main()
{
int A;
int N, K;
cin >> A >> N >> K;//按要求输入的第一行
//下面的for是将输入的节点先保存到全局的链表数组里,为后面“按照初始顺序”插入vector作准备
for (int i = 0; i < N; i++)
{
int a, k;
int d;
cin >> a >> d >> k;//每组的输入
r[a] = { a,d,k };
}
//以下是将“有效的节点”push进vector中,以及计算实际链表长度sum
int sum = 0;
vector<node> s;
for (int i = A; i != -1; i = r[i].next)
{
s.push_back(r[i]);
sum++;
}
/*这里先不管三七二十一,把vector先按“每K个”的原则反转一次,i != s.end() - sum % K很好理解,就是这样循环到最后剩下的n个小于K,这剩余部分是不需要反转的,所以到这个n个的部分的时候就可以跳出for循环了*/
for (auto i = s.begin();i != s.end() - sum % K; i += K)
{
reverse(i, i + K);
}
/*这样一来就很简单了,直接从头开始把当前的next值赋值为其下一个节点的地址即可,一直循环到最后一位位置,注意最后一位需要特殊处理,不解释*/
for (int i = 0; i < s.size(); i++)
{
//对于最后一位,要特殊处理
if (i == s.size() - 1)
{
s[i].next = -1;
break;
}
s[i].next = s[i + 1].address;
}
//然后就是按格式输出拉,注意五位左对齐,ez
for (int i = 0; i < s.size()-1; i++)
{
printf("%05d %d %05d\n", s[i].address, s[i].data, s[i].next);
}
printf("%05d %d %d\n", s[s.size() - 1].address, s[s.size() - 1].data, s[s.size() - 1].next);
return 0;
}