给定一个单链表 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; }
   |