L2-022 重排链表
给定一个单链表 L~1~→L~2~→…→L~n-1~→L~n~,请编写程序将链表重新排列为 L~n~→L~1~→L~n-1~→L~2~→…。例如:给定L为1→2→3→4→5→6,则输出应该为6→1→5→2→4→3。
输入格式:
每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数,即正整数N (<= 10^5^)。结点的地址是5位非负整数,NULL地址用-1表示。
接下来有N行,每行格式为:
Address Data Next
其中Address是结点地址;Data是该结点保存的数据,为不超过10^5^的正整数;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.用结构体数组存放链表节点。
2.首先要对链表做一次清洗,即可能不是一条完整的链表,要把多余的筛选出去。方法是给每个节点做一个标记,初始为很大的数,清洗时为其赋上当前序号。
3.用sort排序,这样就把合法的节点排在前面了,自皇后节点间的关系就不用next了,二是按照结构体数组的序号。
4.最终要输出的可能是偶数或奇数,所以最后可能会剩下。我选择把最后的1或2个单独输出。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
struct Node{
int data,next,address;
int num;
Node(){
num=maxn;
}
}node[maxn];
bool cmp(Node a,Node b){
return a.num <b.num ;
}
int main(){
int n,start;
scanf("%d%d",&start,&n);
for(int i=0;i<n;i++){
int s;
scanf("%d",&s);
scanf("%d%d",&node[s].data ,&node[s].next );
node[s].address =s;
}
int p=start,cnt=0;
while(p!=-1){
node[p].num =cnt++;
p=node[p].next ;
}
sort(node,node+maxn,cmp);
int i=0,j=cnt-1;
while(j-i>1){
printf("%05d %d %05d\n",node[j].address ,node[j].data ,node[i].address );
j--;
printf("%05d %d %05d\n",node[i].address ,node[i].data ,node[j].address );
i++;
}
if(j-i==1){
printf("%05d %d %05d\n",node[j].address ,node[j].data ,node[i].address );
printf("%05d %d -1",node[i].address ,node[i].data);
}else{
printf("%05d %d -1",node[j].address ,node[j].data);
}
return 0;
}