当前位置:网站首页>PAT_甲级_1074 Reversing Linked List

PAT_甲级_1074 Reversing Linked List

2020-11-09 12:10:00 乔梓鑫

题目大意:

现有一个长度为N,起点为begin_address的单链表,要求每K个结点进行逆置,最后不够K个结点的不用逆置,要求输出最后逆置完成的单链表。

算法思路:

这里采用模拟单链表逆置的方法,我们使用node数组存储所有输入的节点,result存储最后逆置结束后的单链表。对于单链表的逆置应该想到头插法,于是我们首先为result链表创建一个头结点,这里头结点的地址得保证一定不在输入的链表之中,于是选取了100004作为头结点地址。然后计算该单链表有几组需要逆置的结点,使用group变量保存,对于每一组,我们使用头插法插入到新建链表result中,这样就完成了K个结点的逆置,同时为了方便更新头结点的位置,我们使用tail来标记result尾节点的位置,在第一次插入的时候更新为插入节点的地址。这样在每一组插入完毕后就更新头结点位置为tail,以此类推,待所有组的节点均插入到result链表之中。最后判断是否还剩余结点,如果还有,那么用尾插法插入到result链表中,然后从头结点的下一个结点输出该新链表即可。

注意点:

1、对于PAT的题目有可能输入的数据无效,尤其是单链表,所有我们得先遍历一遍链表,统计链表有效结点个数count(在输入单链表上的节点个数),目的是为了计算逆置的组数group
2、由于题目给的地址全是5位数字,输出也得保证是5位数,除了-1例外。
3、判断是否还有剩余插入结点的方法就是work_n是否等于-1,因为等于-1说明所有组数的结点插入完毕后就到达了空结点,后面不可能再有结点
4、对于result链表的获得,一定得新建一个节点p,然后更新p的数据再插入到result中,不要直接更新result的地址,比如result[work_n].address = work_n,因为result[work_n]表示的是节点,节点都没有添加进链表中,如何记录地址信息呢?
5、可以使用建立addressdata,addressnext的映射关系,直接逆置address,然后其next为上一个节点的address来处理,但是并没有直接逆置单链表直观(容易想到)。

提交结果:

image.png

AC代码:

#include <cstdio>

using namespace std;

struct Node{
    int address;
    int data;
    int next;
}node[100005],result[100005];

int main(){
    int begin_address,N,K;
    scanf("%d %d %d",&begin_address,&N,&K);
    Node n{};// 暂存输入的每一个节点
    for (int i = 0; i < N; ++i) {
        scanf("%d %d %d",&n.address,&n.data,&n.next);
        node[n.address] = n;
    }
    // 统计输入的链表中有效节点的个数
    int count = 0;
    int work_n = begin_address;//工作在node链表上的指针
    while (work_n!=-1){
        ++count;
        work_n = node[work_n].next;
    }
    // 计算可以逆置的组数
    int group = count/K;
    // 创建result链表的头结点
    Node head{100004,0,-1};
    result[head.address] = head;
    // 对于每一组的每个节点采用头插法插入到result链表中去
    work_n = begin_address;// 重置work_n
    int begin = head.address;// result的头指针
    int tail = -1;//result的尾指针,指向最后一个节点
    for (int i = 0; i < group; ++i) {
        for (int j = 0; j < K; ++j) {
            Node p{work_n, node[work_n].data, result[begin].next};
            result[begin].next = p.address;
            result[p.address] = p;
            work_n = node[work_n].next;// 指向下一个节点位置
            if(j==0){
                tail = p.address;//更新尾节点的地址
            }
        }
        // 每一组节点逆置完毕就更新头节点
        begin = tail;
    }
    while (work_n!=-1){
        // 后面还有一些无需逆置的节点,采用尾插法插入到链表中
        Node p{work_n, node[work_n].data, -1};
        result[begin].next = p.address;
        result[p.address] = p;
        begin = result[begin].next;// 指向result下一个节点位置
        work_n = node[work_n].next;// 指向node下一个节点位置
    }
    for(begin = result[100004].next;begin!=-1;begin = result[begin].next){
        if(result[begin].next==-1){
            printf("%05d %d -1\n",result[begin].address,result[begin].data);
        } else {
            printf("%05d %d %05d\n",result[begin].address,result[begin].data,result[begin].next);
        }
    }
    return 0;
}

版权声明
本文为[乔梓鑫]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000037769925