zoukankan      html  css  js  c++  java
  • 02-1 Reversing Linked List (PAT)

    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
    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
    
    1.使用递归求解
    2.考虑输入中包含孤立节点的情况
     
     1 #include <iostream>
     2 #include <string>
     3 #include <stdlib.h>
     4 #include <iomanip>
     5 using namespace std;
     6 
     7 typedef struct{
     8     int data;
     9     int next;
    10 } dataNode;
    11 
    12 int ReverseList( dataNode node[], int numNode, int lenSub, int firAdd );
    13 
    14 int main()
    15 {
    16     //输入处理
    17     int firAdd, numNode, lenSub;
    18     //第一行处理
    19     cin >> firAdd >> numNode >> lenSub;
    20     dataNode nodes[100000];
    21     int i;
    22     int addr, data, next, head;
    23     for ( i = 0; i < numNode; i++ )
    24     {
    25         cin >> addr >> data >> next;
    26         nodes[ addr ].data = data;
    27         nodes[ addr ].next = next;
    28     }
    29     //排除无效节点,得到有效节点数量
    30     int noNode = firAdd;
    31     int realNum = 0;
    32     while( noNode != -1 )
    33     {
    34         noNode = nodes[ noNode ].next;
    35         realNum++;
    36     }
    37     head = ReverseList( nodes, realNum, lenSub, firAdd );
    38     while ( head != -1 )
    39     {
    40         cout << setw(5) << setfill('0') << head << ' ';
    41         cout << nodes[ head ].data << ' ';
    42         if ( nodes[ head ].next == -1 )
    43         {
    44             cout << nodes[ head ].next << endl;
    45         }
    46         else
    47         {
    48             cout << setw(5) << setfill('0') << nodes[ head ].next << endl;
    49         }
    50         
    51         head = nodes[ head ].next;
    52     }
    53     //输出处理
    54     return 0;
    55 }
    56  
    57 int ReverseList( dataNode nodes[], int numNode, int lenSub, int firAdd )
    58 {
    59     if ( lenSub > numNode || nodes == NULL || firAdd == -1 ) return firAdd;
    60     int current = firAdd;
    61     int prev = -1;
    62     int next = -1;
    63     int count = 0;
    64     while ( current != -1 && count < lenSub )
    65     {
    66         next = nodes[ current ].next;
    67         nodes[ current ].next = prev;
    68         prev = current;
    69         current = next;
    70         count++;
    71     }
    72     if ( next != -1 )
    73     {
    74         nodes[ firAdd ].next = ReverseList( nodes, numNode - lenSub, lenSub, next );
    75     }
    76     return prev;
    77 }

     非递归解法:

    使用reserver函数对每个子链进行处理,并返回子链反转后的新的头结点的位置。

    需要注意每个子链之间的链接。

    假设需要反转的长度为2,元素个数为4,初始链表为a->b->c->d

    使用reserver函数反转第一个子链得到

    a<-b c->d    反转前的头结点为a,反转后的头结点为b(reserver函数会返回b)

    b->a->c->d 反转后a变为前一个子链的尾结点,将该结点与下一个子链的头结点c连接

    如果剩余元素数量小于反转长度,那么直接输出该链表,但是如果下一个链表也需要反转‘

    那么调用reserver函数处理c,d子链的结果为b->a->c<-d,这时除了反转c,d子链之外,还需要将a->c修改为a->d,正确结果为b->a->d->c

    #include <iostream>
    #include <stdlib.h>
    #include <iomanip>
    using namespace std;
    
    #define MAXSIZE 100001
    
    typedef struct
    {
        int data;
        int next;
    }dataNode;
    
    int Reverse(int head, int K, dataNode *virMem);
    int CheckEnd(int head, dataNode *virMem, int K);
    
    int main()
    {
        ////测试数据
        //int head = 100;
        //int temp = head;
        //int newHead, subHead;
        //int N = 6;
        //int K = 4;
        //virMem[0].data = 4;
        //virMem[0].next = 99999;
        //virMem[100].data = 1;
        //virMem[100].next = 12309;
        //virMem[68237].data = 6;
        //virMem[68237].next = -1;
        //virMem[33218].data = 3;
        //virMem[33218].next = 0;
        //virMem[99999].data = 5;
        //virMem[99999].next = 68237;
        //virMem[12309].data = 2;
        //virMem[12309].next = 33218;
        ////测试数据
        int head;
        int temp;
        int newHead, subHead, tempHead;
        int N;
        int K;
        int index;
        int data;
        int next;
        dataNode virMem[MAXSIZE]; //使用数组模拟内存
        cin >> head >> N >> K;
        int startFlag = 0;
        for (int i = 0; i < N; i++)
        {
            cin >> index >> data >> next;
            virMem[index].data = data;
            virMem[index].next = next;
        }
        newHead = head;    //处理完全不进行反转的情况
        while ( CheckEnd(head, virMem, K) != 1 )
        {
            subHead = Reverse(head, K, virMem);    //最初head位置在逆转后变为该子链的最后一个元素
            if ( startFlag == 0 )    //第一组逆转元素
            {
                newHead = subHead;    //取得整个链表逆转后的头指针
                startFlag = 1;
            }
            else
            {
                virMem[tempHead].next = subHead;    //将上一个子链与反转后的子链头连接,第一次反转不执行
            }
            tempHead = head;    //记录上一个子链的最后一个元素
            head = virMem[head].next;    //将head移动到下一段子链的第一个元素    
        }
        temp = newHead;
        while ( temp != -1 )
        {
            cout << setw(5) << setfill('0') << temp << " ";
            cout << virMem[temp].data << " ";
            if ( virMem[temp].next == -1 )
            {
                cout << virMem[temp].next << endl;
            }
            else
            {
                cout << setw(5) << setfill('0') << virMem[temp].next << endl;
            }
            temp = virMem[temp].next;
        }
        return 0;
    }
    
    int Reverse(int head, int K, dataNode *virMem)
    {
        int cnt;    //统计逆转长度
        int posTemp;
        int posNew = head;
        int posOld = virMem[posNew].next;
        cnt = 1;
        while ( cnt < K )    //K个元素,需要逆转K-1次
        {
            posTemp = virMem[posOld].next;
            virMem[posOld].next = posNew;
            posNew = posOld;
            posOld = posTemp;
            cnt++;
        }
        virMem[head].next = posOld;
        return posNew;
    }
    
    int CheckEnd(int head, dataNode *virMem, int K)    //检测子链长度是否小于K,小于K返回1,否则返回-1。该方法可考虑优化,如可先对初始链表进行处理,排除孤立结点统计出待处理链表的真实长度后在进行反转
    {
        int temp = head;
        int i;
        if ( head == -1 )
        {
            return 1;    //链表为空
        }
        for (i = 0; i < K && temp != -1; i++)
        {
            temp = virMem[temp].next;
        }
        if ( i < K )    //剩余长度小于K
        {
            return 1;
        }
        else
        {
            return -1;
        }
    }
  • 相关阅读:
    Cookie和Session的区别
    get和post的区别
    TCP和UDP的区别
    TCP三次握手过程
    docker 安装prometheus
    大数据集群环境搭建之一 hadoop-ha高可用安装
    大数据集群环境 zookeeper集群环境安装
    Centos 脚本中几个特殊符号的作用笔记
    VMware 设置虚拟机Centos 上网的两种方式
    大数据集群环境搭建之一 Centos基本环境准备
  • 原文地址:https://www.cnblogs.com/liangchao/p/4271129.html
Copyright © 2011-2022 走看看