A1074 Reversing Linked List 分数 25

题目描述

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

题目分析

  • 对链表进行逆置

  • 链表是以静态链表的方式给出的,可以继续用静态链表也可以存到动态链表里

  • 存储在静态链表

  • 法一 data[address] next[address]

  • 法二 struct node{int data,int next}Nodes[5] 结构体数组的下标就是节点的地址

  • 逆置方法

  • 一个入门的方法:swap(i,i+K) ,swap(i+1,i+K-1)swap(i+2,i+K-2)

  • 一个重要的思想:链表不好处理,可以放到数组里

  • 于是就放到数组里,然后相当于对数组进行逆置,reverse()函数

  • 于是总体的方法

  • 读入静态链表

  • 按照节点顺序存储到数组(vector)中

  • 逆置

  • 生成next地址

  • 输出

问题

  • 节点(addr,data,next)是存储在一起的,我们是要改变链表节点的顺序,而一旦改变节点的顺序,这个next就变了(但是data和地址是不变的),因此需要重新生成一下next节点

  • 输出00001 printf("%05d",data); 但是如果是-1,需要单独来进行输出

  • 对于for循环中,只能循环到 sum- sum%k的地方,这个终止条件很好,也可以是用一下min函数

  • reverse(it,min(it+k,array.end()));(但是会超时,也是慎用)

思考与收获

  • 对于终止条件一定要判断好!

  • min有时候会超时

  • 思路先理清晰再写代码

  • 静态链表可以用数组来存,链表也是

代码

刚开始有俩测试点不能通过

后来修改了终止条件,才通过

可以见到终止条件十分重要

#include <iostream>
#include <vector>
#include<algorithm>
#include <iterator>
using namespace std;




struct node{
    int data;
    int next;
}List[100005]; //为何多加5个?
int main() {

//   首先将静态链表读入
//    两种方法读入静态链表
    int initaddress,num,k;
    scanf("%d %d %d",&initaddress,&num,&k);
    int addr,data,next;
    for(int i=0;i<num;i++)
    {
        scanf("%d %d %d",&addr,&data,&next);
        List[addr].data = data;
        List[addr].next = next;
    }
//   将静态链表转为数组,数组的排序是链表的排序,数组的内容是节点的 地址 和  数据
//    由于不一定所有的节点都是有效的,不可以直接去以num为个数进行循环,转为判断next是否等于-1即可

    vector<vector<int>> array ;
    int sum=0;
    int addr1 = initaddress;
    int nextaddr=-2;
    while(nextaddr!=-1)
    {
        vector<int> temp;//保存data和地址
        temp.push_back(List[addr1].data);
        temp.push_back(addr1);
        array.push_back(temp) ;
        nextaddr = List[addr1].next;
        addr1 = nextaddr;
        sum++;
    }
//   对数组的部分进行reverse,由于
    int i=0;
    for(vector<vector<int>> ::iterator it= array.begin() ;it!=array.end();it+=k)
    {
        i+=k;
        if(i>sum)//边界条件不能判断出错 i=sum的时候,当然是不能中断的了
        {
            break;
        }
//        reverse(it,min(it+k,array.end()));//直接用这个会超时!
        reverse(it, it+k );

    }
// 这个时候是新的顺序,但是不是静态链表形式,压根没有next地址,next地址是下一个,生成一下
    int newnextaddr[num+2];
    int j=0;
    for(auto it:array)
    {
        newnextaddr[j++]  = it[1];
    }
    newnextaddr[j++]  = -1;
    int m=1;
    for(auto it:array)
    {
        if(newnextaddr[m]==-1)
        {
            printf("%05d %d %d\n",it[1],it[0],-1);
        } else{
            printf("%05d %d %05d\n",it[1],it[0],newnextaddr[m]);
        }
        m++;

    }
    return 0;
}

更简洁的代码(但不好理解)重点在17行

#include <iostream>
using namespace std;
int main() {
    int first, k, n, sum = 0;
    cin >> first >> n >> k;
    int temp, data[100005], next[100005], list[100005], result[100005];
    for (int i = 0; i < n; i++) {
        cin >> temp;
        cin >> data[temp] >> next[temp];//用data[],next[]来存储静态链表
    }
    while (first != -1) {
        list[sum++] = first;
        first = next[first];
    }
    for (int i = 0; i < sum; i++) result[i] = list[i];//复制一下数组
    for (int i = 0; i < (sum - sum % k); i++)// i 的范围是这个!很好
        result[i] = list[i / k * k + k - 1 - i % k];// k-1 - i%k
    for (int i = 0; i < sum - 1; i++)
        printf("%05d %d %05d\n", result[i], data[result[i]], result[i + 1]);
    printf("%05d %d -1", result[sum - 1], data[result[sum - 1]]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45621688/article/details/129497017