L2-022 重排链表 C++方法解答

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

希望对你有帮助! 

你可能感兴趣的:(链表,c++,数据结构)