给定一个单链表 L1→L2→⋯→L n−1 → L n,请编写程序将链表重新排列为 L n→L1→L n−1→L2→⋯。例如:给定L为1→2→3→4→5→6,则输出应该为6→1→5→2→4→3。
输入格式:
每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数,即正整数N (≤105)。结点的地址是5位非负整数,NULL地址用−1表示。
接下来有N行,每行格式为:
其中Address
是结点地址;Data
是该结点保存的数据,为不超过105的正整数;Next
是下一结点的地址。题目保证给出的链表上至少有两个结点。
输出格式:
对每个测试用例,顺序输出重排后的结果链表,其上每个结点占一行,格式与输入相同。
输入样例:
1 2 3 4 5 6 7
| 00100 6 00000 4 99999 00100 1 12309 68237 6 -1 33218 3 00000 99999 5 68237 12309 2 33218
|
输出样例:
1 2 3 4 5 6
| 68237 6 00100 00100 1 99999 99999 5 12309 12309 2 00000 00000 4 33218 33218 3 -1
|
思路
静态链表解题套路(因为过于套路,近期的PAT乙级、甲级都没有出现过,不过sort排序的套路还是有的)
静态链表:使用数组索引模拟结点地址,本题的地址是5位整数
还原链表后,设立两个指针,分别指向链表头部和尾部,每次先取出尾部节点,再取出头部节点,直到两指针相遇
泛化来说,指针不一定是(C语言里int*)这样的指针,指针的意义是获取数据所在位置,数组索引也可以是指针
知识点:静态链表、constexpr语法
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include <iostream> #include <vector>
using namespace std; constexpr int MAX_SIZE = 100001;
struct Node { int add; int data; };
int main() { int head, n; cin >> head >> n; int data[MAX_SIZE], next_add[MAX_SIZE]; while(n--) { int a, b, c; cin >> a >> b >> c; data[a] = b; next_add[a] = c; } vector<Node> ve; while(head != -1) { ve.push_back(Node{head, data[head]}); head = next_add[head]; } int i = 0, j = (int)ve.size() - 1; vector<Node> ret; while(i < j) { ret.push_back(ve[j]); ret.push_back(ve[i]); i++, j--; } if(i == j) { ret.push_back(ve[i]); } if(!ret.empty()) { for(int i = 0; i < (int)ret.size() - 1; i++) { printf("%05d %d %05d\n", ret[i].add, ret[i].data, ret[i + 1].add); } printf("%05d %d -1\n", ret.back().add, ret.back().data); } return 0; }
|