题目描述
给一个常量K和一个单链表L,对L上的每K个元素进行反转
例如,给定L为 1→2→3→4→5→6
如果K=3,那么必须输出 3→2→1→6→5→4
如果K=4,那么必须输出 4→3→2→1→5→6.
输入规范:
每个输入文件都包含一个测试用例。对于每种情况,第一行包含第一个节点的地址,一个正N (≤10^5 ) 是节点总数,一个正 K (≤N) 是要反转的子列表的长度。节点的地址为 5 位非负整数,NULL 用 -1 表示。
然后是 N 行,每行描述一个节点,格式如下:
“接下来处理数据”
其中 Address 是节点的位置,Data 是整数,Next 是下一个节点的位置。
输出规范:
对于每种情况,输出生成的有序列表。每个节点占用一行,并以与输入相同的格式打印。
Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
代码展示
本解法的关键是将使用两个数组来存储链表,其中一个结构体数组的索引即链表节点地址,数组内部存放数据和下一个节点地址;另一个数组按线性顺序存放链表节点地址,然后仅对后者进行反转即可,使得操作更为简单
一个更直白的解释就是:把这个结构体数组当做一个数据库,对另一个数组进行反转后,然后按照顺序去这个数据库中查找相应的节点信息即可。
如果对结构体数组进行反转,那么太过于繁琐,而且实现较复杂,不建议这么操作
#include <iostream>
#include <algorithm>
#define MAXSIZE 100000
struct listNode
{
int Data;
int Next;
}a[MAXSIZE];
int main()
{
int head, N, K;
std::cin >> head >> N >> K;
int list[MAXSIZE];
for (int i = 0; i < N; i++)
{
int address, data, next;
std::cin >> address >> data >> next;
a[address] = { data, next };
}
//按节点先后顺序存于list中
list[0] = head;
int count = 1; //list中每存放一个节点,count数加1
int curAddress = a[head].Next;
while(curAddress != -1)
{
list[count++] = curAddress;
curAddress = a[curAddress].Next;
}
//根据K值进行反转
int j = 0;
while (j + K <= count)
{
std::reverse(&list[j], &list[j + K]);
j += K;
}
//输出反转后的链表
int i = 0;
for (; i < count - 1; i++)
{
int address = list[i];
printf("%05d %d %05d\n", address, a[address].Data, list[i+1]);
}
printf("%05d %d -1\n", list[i], a[list[i]].Data);
return 0;
}