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 #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; } }