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;
    }
}
原文地址:https://www.cnblogs.com/liangchao/p/4271129.html