Problem Description
Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.
Input Specification
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤105) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Address Data Next
where Address is the position of the node, Data is an integer, and Next is the position of the next node.
Output Specification
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
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
Solution
- 首先将数据读入并以合适的方式保存。
- 根据数组的下标特性,dataArr 的元素是保存的数据,下标是对应的地址,再有一个 nextAddressArr 数组来存某数据的下一个地址,下标是对应的地址。
- 将数据全部存到 dataArr 与 nextAddressArr 中后,利用链表的遍历思想按照链表顺序把数据存入 addressList 数组。
- 这个时候同时要利用 N 来获取到在链表内元素的个数。因为样例内有不在链表上的结点,那些就不用管,把结点排好序后 N 就是在链表内的结点数。理解 ++ 操作的作用。
- 接下来利用双重循环和数学平均的操作,把每一个区间内的数据地址在 addressList 中头尾交换实现逆序。
- 最后输出时利用 %05d 来给地址占位。最后一个数据特判输出 -1 。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, firstAddress, n, k, curAddress, data, nextAddress, tmp, sum, N;
int dataArr[100001], nextAddressArr[100001], addressList[100001];
scanf("%d %d %d", &firstAddress, &n, &k);
for (i = 0; i < n; i++) {
scanf("%d %d %d", &curAddress, &data, &nextAddress);
dataArr[curAddress] = data;
nextAddressArr[curAddress] = nextAddress;
}
N = 0;
while (firstAddress != -1) {
addressList[N++] = firstAddress;
firstAddress = nextAddressArr[firstAddress];
}
for (i = 0; i < N - N % k; i += k) {
sum = i * 2 + k - 1;
for (j = 0; j < k / 2; j++) {
tmp = addressList[i + j];
addressList[i + j] = addressList[sum - i - j];
addressList[sum - i - j] = tmp;
}
}
for (i = 0; i < N - 1; i++) {
printf("%05d %d %05d\n", addressList[i], dataArr[addressList[i]], addressList[i + 1]);
}
printf("%05d %d -1\n", addressList[N - 1], dataArr[addressList[N - 1]]);
return 0;
}
教学中的方法是依照指针操作的思想来写的逆序算法。