给定一个单链表 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
好了,在这里我们阅读题目可以发现,这是一道很经典的需要用结构体来做的链表类型的题目,那么在思考如何完成代码的时候,我们第一时间也许会想到做一个链表像这样:
typedef struct {
int address;
int data;
int next;
int id;
}Link;
但是在我们后续需要对不按顺序给出的链表节点进行排序时候,会发现一个问题 :
我们如何调用link[ i ].address呢?
是不是像这样呢?
for(int i = head ; i != -1 ; i = link[i].next){
link[i].id = idCount++;
}//此处的idCount是用来自增,给链表的顺序赋值的
乍一看好像没啥问题,但是真正运行起来我们很容易忽视这个点,你会发现欸,为什么出现段错误了?我啥也没做啊咋就超栈了???
这时候细心一看就会发现,原来我们循环里i是利用地址找寻下一个节点,而在循环体中赋值的时候,我们习惯将 i 看作自增变量,那么这里就会出现一个问题: link[ 地址 ]. id ,这很显然是行不通的,因为link作为一个数组变量,它的最大值就是我们需要输入的n,而这里我们用地址带入了结构体数组link中查找的参数,那很显然就一定会出现超栈问题。
所以应该如何解决呢?那就是再新建一个数组,专门按顺序记录每个节点的地址就好了,随后也可以删去结构体定义时候的address变量了,随后需要查找地址的时候直接在该数组中调用就可以了。
但是还有一个问题就是奇偶数的区别了。
我们发现在对于偶数节点和奇数节点的链表处理方法是不同的:
对于偶数:6 1 5 2 4 3
而对于奇数:5 1 4 2 3 不难发现它有些顺序是相互反过来的,那么就要在输出的时候额外注意一下打印的逻辑就好了。如果看作两个节点一组的话,那么偶节点的结束就在每一组的末尾“-1”,而奇数节点的链表则会出现在最后一组的第一个节点处“-1”结束。
#include
using namespace std;
typedef struct{
int data ;
int next;
int id;
}Link;
int head, n , idCount;
const int N = 1e5 + 10;
int main (){
cin >> head >> n;
vector link( N );
vector address;//最后排序好的所有地址集合
for(int i = 0 ; i < n ; i ++){
int ad, d , ne;
cin >> ad >> d >> ne;
link[ad].data = d;
link[ad].next = ne;
}//到这里完成数据的储存
idCount = -1 ;
for(int i = head ; i != -1 ; i = link[i].next){
link[i].id = idCount++;//这里是从头到尾遍历链表,然后进行排序(从0开始)
address.push_back(i);
}
//这里开始打印结果
//在偶数的情况下是这样的 :6 1 5 2 4 3;
//思考一下如果是奇数个的节点个数呢:5 1 4 2 3;
for(int i = 0 ; i < n ; i ++){
if( n%2 == 0){
printf("%05d ",address[idCount - i]);
cout << link[ address[idCount - i] ].data << " ";
printf("%05d\n",address[i]);
printf("%05d ",address[i]);
cout << link[ address[i] ].data << " ";
if(abs((idCount - i) - i) == 1){
cout << "-1" << endl;
break;
}
else printf("%05d\n",address[idCount - i- 1]) ;
}
//需要分别对奇数和偶数的情况进行区分,下面是奇数的情况
else {
printf("%05d ",address[idCount - i]);
cout << link[ address[idCount - i] ].data << " ";
if(abs((idCount - i) - i) < 1){
cout << "-1" << endl;
break;
}
else printf("%05d\n",address[i]);
printf("%05d ",address[i]);
cout << link[ address[i] ].data << " ";
printf("%05d\n",address[idCount - i- 1]) ;
}
}
}
希望对你有帮助!