分析:
- 用结构体数组来模拟实现链表,每个元素的下标代表其地址
- 新开一个数组,按顺序存储一个完整链表中的所有结点
- 再开一个数组,将2中数组的元素按每K个反向存储的方式存储,最后输出
代码如下
#include <iostream>
using namespace std;
struct Node{
int ad, data, next;
};
struct Node Nd[100003]; //Nd数组的每一个元素模拟Node结点,包括值和下一个结点的地址 ,元素下标是该结点的地址值
struct Node Temp1[100005]; //记录完整链上的结点
struct Node Temp2[100005]; //记录要输出的结点
int main() {
int Ad, N, K;
scanf("%d %d %d", &Ad, &N, &K);
for(int i = 0; i< N; i++) {
int a, b, c; scanf("%d %d %d", &a, &b, &c);
Nd[a].ad = a; Nd[a].data = b; Nd[a].next = c;
}
struct Node p = Nd[Ad]; //遍历链表,p表示当前链表
int cnt = 0; //cnt记录放进Temp中的结点数,到达K时倒着输出
while(1) { //遍历链表
Temp1[++cnt].ad = p.ad; Temp1[cnt].data = p.data; Temp1[cnt].next = p.next;
if(-1 == p.next) { //添加一个地址为-1的尾结点
Temp1[++cnt].ad = -1; Temp1[cnt].data = -1; Temp1[cnt].next = -1; break;
}
else p = Nd[p.next];
}
int x = 1, y = x+K-1, z = 0; //x,y表示反转链的首尾结点下标,z表示当前存储结点下标
while(1) {
if(x+K-1 <= cnt-1) { //倒转
for(int i = y; i >= x; i--)
Temp2[++z] = Temp1[i];
x = y + 1;
if(x+K-1 <= cnt-1) y = x+K-1;
}
else {
Temp2[++z] = Temp1[++y];
}
if(y > cnt-1) break;
}
Temp2[++z] = Temp1[++y]; //加上地址为-1的最后一个结点
for(int i = 1; i < cnt; i++) {
printf("%05d %d ", Temp2[i].ad, Temp2[i].data);
if(-1 == Temp2[i+1].ad) printf("-1\n");
else printf("%05d\n", Temp2[i+1].ad);
}
}
细节处理:
- 为了将最后一个数据常规化,在存储链表结点时,新增了一个地址为1的尾结点,便于判断和输出,最后并不输出该结点
- 虽然开3个数组有点浪费空间,不过这样处理逻辑上便于理解
反思(很多不该犯的错误):
- 第一遍提交有样例反馈运行超时,遂怀疑算法思路有问题,自闭;
然而其实是我循环条件没写对,导致了无限循环 - 曾经想过在按顺序统计链表结点的过程中顺带每K个元素倒着输出;
然而这样在倒着输出最后一个元素时,它的next值无法确定,因为根本就不知道下一个元素是否又包含在另外一个K中 - 最主要的问题还是因为没有仔细考虑直接动手的原因,在做题前还是要多想想可能出现的情况,再动手
- debug过程中,if条件明明正确却不执行,这里卡了我很久,最后发现是数组多声明了一次,且最后声明的时候开的空间很小,if判断时已经越界了(太傻)
PS:
- 本题如果采用一些库函数就非常好做了