题目: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;
}