• PTA 5-2 Reversing Linked List (25) [法一]


    题目:http://www.patest.cn/contests/pat-a-practise/1074

    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 (<= 105) 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         //第一行:链表的首地址add,结点个数n,每隔k个进行一次反转
    00000 4 99999     //后面n行:结点的地址address,数据data,下一个结点的地址next
    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

    题目大意:

    反转单链表,给定常数K和单链表L,要求按每K个节点反转单链表,如:L: 1->2->3->4->5->6 K=3,输出:3->2->1->6->5->4,如果K=4,输出:4->3->2->1->5->6.

    特殊情况:

    1. 有其他链表干扰(即有多个-1出现):找链表有效长度

    2. k=1 或者 k=n :不变 或者 全部逆序

    3. 需逆序的起点大于有效长度 : 直接输出原链表

      推荐测试:

    1. k=1或者k=n:

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

    2. 有其他链表干扰(即有多个-1出现):

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

     - 定义结构

    struct Node {
        int iData;
        int iNext;
    };
    const int iMaxLen = 100004;
    int iHead; //!首地址
    int N, K;
    Node NodeList[iMaxLen];
     - paixu():

    1. 找有效长度:判断next是否遇到-1
    2. 若需逆序的起点 > 有效长度(k > iEffectiveLength):doPrint(iHead)
    3. 更新结点总数 N 为有效长度 iEffectiveLength

    K>1:
    4. 初始化新链表(反转后)的首尾地址

    // iNewHead,iLastTail 表示新链表(反转后)的首尾地址
    // iTheHead,iTheTail 表示链表中反转的每一小节的开头和结尾
    reverseK(iHead, K, &iTheHead, &iTheTail);
    iNewHead = iTheHead;
    iLastTail = iTheTail;

    5. 计算反转次数:

    iReserveCount = N/K – 1

    6. 每K个翻转一次

    for(int i = 0; i < iReverseCount; ++i) {
        reverseK(NodeList[iTheTail].iNext, K, &iTheHead, &iTheTail);
            NodeList[iLastTail].iNext = iTheHead;
            iLastTail = iTheTail;
    }

    K<=1:

    iNewHead = iHead;

    7.输出链表:

    doPrint(iNewHead);
     - reverseK():

    从 iStartHead 开始反转k个元素(原理即单链表反转)

    int reverseK(int iStartHead, int iK, int *pHead, int *pTail)
    //iStartHead:每一小节开始反转的结点
    //node1,node2,nodeTmp:可看作反转所需的三个指针
    
    完整代码:
    #include <cstdio>
    struct Node {
        int iData;
        int iNext;
    };
    const int iMaxLen = 100004;
    int iHead; //!首地址
    int N, K;
    Node NodeList[iMaxLen];
    
    void doPrint(int iNodeAdd)
    {
        while(iNodeAdd!=-1){
            if(NodeList[iNodeAdd].iNext == -1){
                printf("%.5d %d -1
    ",iNodeAdd,NodeList[iNodeAdd].iData);
                break;
            }
            printf("%.5d %d %.5d
    ",iNodeAdd, NodeList[iNodeAdd].iData, NodeList[iNodeAdd].iNext);
            iNodeAdd = NodeList[iNodeAdd].iNext;
        }
    }
    //!从iStartHead开始反转k个元素
    int reverseK(int iStartHead, int iK, int *pHead, int *pTail)
    {
        //!只有一个节点
        if(-1 == iStartHead || iK <= 1)
            return -1;
        if(2 == iK){
            int node1 = iStartHead;
            int node2 = NodeList[iStartHead].iNext;
            NodeList[node1].iNext = NodeList[node2].iNext;
            NodeList[node2].iNext = node1;
            *pHead = node2;
            *pTail = node1;
            return 0;
        }
        *pTail = iStartHead;
        int node1 = iStartHead;
        int node2 = NodeList[iStartHead].iNext;
        int nodeTmp = -1;
        for(int i = 0; i < iK - 1; ++i){
            nodeTmp = NodeList[node2].iNext;
            NodeList[node2].iNext = node1;
            node1 = node2;
            node2 = nodeTmp;
        }
        *pHead = node1;
        NodeList[*pTail].iNext = node2;
        return 0;
    }
    void paixu() {
        int iNodeTmp = iHead;
        //!找有效结点的长度:即判断next是否遇到-1
        int iEffectiveLength = 1;
        while(-1 != NodeList[iNodeTmp].iNext) {
            ++iEffectiveLength;
            iNodeTmp = NodeList[iNodeTmp].iNext;
        }
        //!需逆序的起点大于有效长度
        if(K > iEffectiveLength){
            //!直接输出当前没有逆序的结点
            doPrint(iHead);
        }
        //!有效长度覆盖输入的结点总个数
        N = iEffectiveLength;
    
        int iNewHead;
        if(K > 1) {
            int iTheHead, iTheTail;
            int iLastTail;
            //!first init reverse to decide the new head
            reverseK(iHead, K, &iTheHead, &iTheTail);
            iNewHead = iTheHead;
            iLastTail = iTheTail;
                            
            int iReverseCount = N / K - 1;  //!反转次数       
            for(int i = 0; i < iReverseCount; ++i) {
                reverseK(NodeList[iTheTail].iNext, K, &iTheHead, &iTheTail);
                NodeList[iLastTail].iNext = iTheHead;
                iLastTail = iTheTail;
            }
        }
        else
            iNewHead = iHead;
        doPrint(iNewHead);
    }
    int main() {
        //!初始化 data和next都初始化为0
        for(int i = 0; i < iMaxLen; ++i) {
            NodeList[i].iData = 0;
            NodeList[i].iNext = -1;
        }
        //!输入首地址,结点总数,需逆序到的数
        scanf("%d %d %d", &iHead, &N, &K);
        int iSingleNodeAddress, iSingleNodeData, iSingleNodeNext;
        for(int i = 0; i < N; ++i) {
            scanf("%d %d %d", &iSingleNodeAddress, &iSingleNodeData, &iSingleNodeNext);
            NodeList[iSingleNodeAddress].iData = iSingleNodeData;
            NodeList[iSingleNodeAddress].iNext = iSingleNodeNext;
        }
        paixu();
        return 0;
    }
    
  • 相关阅读:
    Devexpress [汇总链接]
    [转]修改LayoutControlitem容器内的控件长宽
    How to hide border of XtraTabControl
    CEF / Chromium 重新编译2018 官网地址 一路是坑 千万别跟着官方step by step走一定多思考多查资料 因为改动地方太多了编译都每个版本都不一样
    c#:配置引用程序集的路径(分离exe和dll)和 如何处理[dllImport]中的程序集的加载 [笔记]
    [redis] -- 缓存雪崩和缓存穿透、缓存击穿问题解决方案篇
    [redis] -- 为什么那么快
    [redis] -- 集群篇
    [spring cloud] -- 服务注册与服务发现篇
    [spring cloud] -- 核心篇
  • 原文地址:https://www.cnblogs.com/claremore/p/4802164.html
Copyright © 2020-2023  润新知