// 正确代码
#include <bits/stdc++.h>
using namespace std;
int Link[100000];
int main() {
int Head, N, K, Address, count = 0;
cin >> Head >> N >> K;
map<int, int>Data, Next;
while (N--) {
cin >> Address;
// 以Address为key 读取Data和Next
cin >> Data[Address] >> Next[Address];
}
while (Head != -1) {
// 数组从count = 0开始 按顺序存链表地址 统计链表结点数count
Link[count++] = Head;
// 读取下一个结点地址
Head = Next[Head];
}
// 局部反转 当前Data编号i 小于 可完整反转一次的编号时执行
for (int i = 0; i < count - count % K; i += K)
reverse(Link + i, Link + i + K);
// 用Address为key(索引)读取Data Next即数组下一个元素储存的地址
for (int i = 0; i < count - 1; ++i)
printf("%05d %d %05d\n", Link[i], Data[Link[i]], Link[i + 1]);
// 最后一个结点 手动 -1
printf("%05d %d -1", Link[count - 1], Data[Link[count - 1]]);
}
// 错误代码 说明了编号与结点地址的顺序不一定一致
#include <bits/stdc++.h>
using namespace std;
struct Node{
string address;
int data;
}node[100000];
int main() {
string address, next;
int data, size, k;
// 读取首地址 结点数 反转数
cin >> address >> size >> k;
// 读取结点信息
for(int i = 0; i < size; i++){
cin >> address >> data >> next;
node[i].address = address, node[i].data = data;
}
// 以编号升序排序
sort(node, node + size, [](Node a, Node b){
return a.data < b.data;
});
// 用reverse()函数对结构体数字局部反转
// 当前编号+k 不小于 元素个数时停止循环 如当前编号是3 k=4 则 4+4 !< 6
for(int i = 0; i + k < size; i += k)
reverse(node + i, node + i + k);
// 遍历到Size()-1个对象
int i = 0;
for( ; i < size -1; ++i){
cout << node[i].address << " " << node[i].data << " " << node[i+1].address << endl;
}
// 最后一个输出下一个地址为 -1
cout << node[i].address << " " << node[i].data << " " << -1;
}
这题目的关键,要看到每个结点在反转前后,其自身的地址 Address 和编号 Data 仍然是一致的,改变在指向下一个结点的地址改变了。
而地址跟编号对应,那么一开始就可以用 map,以地址为 key 储存编号为 val。那么后面就可以需要的时候再通过这个容器来读取对应结点的地址。这样我们就解决了编号的问题,再看当前地址和下一个结点地址。
从输出可以看到,虽然编号逆转了,但结点之间的指向仍然是按照顺序方式不断指向下一个,除了最后一个结点指向 -1 不存在,其他可以从排好序的结点中,直接获取下一个结点的地址输出。这样就解决了下一个结点的地址问题。
而关于原始链表的顺序,需要根据结点的下一个地址连起来。所以最开始除了用 map 存储 Data 外还需另一个容器来存储反转前结点与下一地址的关系。来将结点按顺序放入数组里面。
得到正确顺序的数组,就可以用 reverse() 函数将局部 K 个元素反转。最后输出的时候按顺序输出地址和编号,读取下一个结点输出下一位地址,并注意最后一个结点的下一个地址为 -1 即可。
(被输出样例忽悠了,以为编号和原本的结点地址是一一对应,可以直接按编号来排出顺序。比如下面那个错误代码,但只有样例看起来这样,实际输出只能得个及格分。)
data
迭代器不是想移动到哪就移动到哪,只能够 ++ -- 左右移动,或者重新赋值。
关于set容器的find,如果set的元素是struct结构体对象,那么查找的时候也需要传入一个结构体。
set容器不能局部reverse,参考代码里面局部反转用的是数组。如果全部反转遍历倒是可以用rbegin()和rend()。
按照参考代码的写法,最后输出Next的时候,只需要读取数组的下一位元素输出其地址即可。