一、题目
给定一个单链表 L1 → L2 →⋯→ Ln−1 → Ln ,请编写程序将链表重新排列为 Ln → L1 → Ln−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 Next
其中Address是结点地址;Data是该结点保存的数据,为不超过105 的正整数;Next是下一结点的地址。题目保证给出的链表上至少有两个结点。
输出格式:
对每个测试用例,顺序输出重排后的结果链表,其上每个结点占一行,格式与输入相同。
输入样例:
00100 6
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
输出样例:
68237 6 00100
00100 1 99999
99999 5 12309
12309 2 00000
00000 4 33218
33218 3 -1
二、方法1
1、思路
使用了两个一维数组,按照节点顺序存放数据,一个数组存放节点,一个数组存放值;使用了双指针的思路,头指针和尾指针分别从前后开始遍历,交替移动,即可。
易错点提示:
- 将数据存放进一维数组的时候,因为跳出循环的条件为遍历至尾结点,所以其实是没有将尾结点的数据存放进去的,需要手动存放;
- 需要判断头尾指针谁进行移动,这个可以利用遍历时的单双数完成;
- 注意双指针移动时的临界条件,需要单独讨论一下。
2、代码
#include<stdio.h>
#define max 100005
typedef struct Node
{
int address;
int data;
int next;
}node;
node a[max];
int pre, n, last; // pre:首节点 last:尾结点
int address, data, next; // 输入
int i, j, k; // 遍历
int a1[max], a2[max]; // a1:节点 a2:值
int cnt = 0; // 计数
int t; // 中间变量
int left, right; // 双指针
int main()
{
scanf("%d %d", &pre, &n);
for (i = 0; i < n; i++)
{
scanf("%d %d %d", &address, &data, &next);
a[address].address = address;
a[address].data = data;
a[address].next = next;
//记录尾节点
if (next == -1)
last = address;
}
t = pre;
while (t != last)
{
// 按照节点顺序存值
a1[cnt] = a[t].address; // a1存放节点
a2[cnt++] = a[t].data; // a2存放值
t = a[t].next; // 更新节点
}
// 存放尾结点
a1[cnt] = a[t].address;
a2[cnt++] = a[t].data;
left = 0, right = cnt - 1;
for (j = 1; j <= cnt; j++)
{
if (j % 2 == 1)
{
if (j == cnt)
printf("%05d %d -1\n", a1[right], a2[right]);
else
{
printf("%05d %d %05d\n", a1[right], a2[right], a1[left]);
right--;
}
}
else
{
if (j == cnt)
printf("%05d %d -1\n", a1[left], a2[left]);
else
{
printf("%05d %d %05d\n", a1[left], a2[left], a1[right]);
left++;
}
}
}
return 0;
}