题目描述:
给定一个常数K以及一个单链表L,请编写程序将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,即最后不到K个元素不反转。
输入格式:
每个输入包含1个测试用例.每个测试用例给出两个正整数N和K,其中N为节点总个数,第二行依次给出N个正整数,分别为链表中的键值.
输出格式:
分行输出结果,每个结果一行.
要求:
以链表形式实现.
注:我的编译环境为visual studio 2017 community.
思路:
我这里采用的是建立一个新的链表的方法,按照要求的顺序来复制原链表的键值.
假设N=6,K=4.
- Tmp初始化为L.Next
- Head初始化为Tmp,然后在计数器下,运行三次Tmp=Tmp.Next,此时Tmp先后指向了K(4)个节点(包括初始化时指向的节点).将Tmp此时指向的节点的键值压入New的栈中,Tmp后移一个节点(即节点5).
- 接下来使用循环将剩余的K-1个(即3个)键值压入栈中: 每次循环开始时Rail初始化为Head,再后移一定的节点(依将要压入栈中的节点而定,节点3Rail要后移2个节点,节点2Rail要后移1个节点,以此类推),到达指定位置后,将键值压入栈中.
- 重复步骤2,3直到剩余的节点数不足以翻转一次.
代码:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <time.h>
#include <iomanip>
#include <math.h>
using namespace std;
struct LinkedListNode
{
int Element;
LinkedListNode* Next;
};
typedef LinkedListNode* LinkedList;
class Stack
{
private:
int NodeNumber;
public:
Stack()
{
NodeNumber = 0;
}
LinkedList Initialize()
{
LinkedList L = new LinkedListNode;
L->Element = 0;
L->Next = NULL;
return L;
}
bool IsEmpty(LinkedList L)
{
return L->Next == NULL;
}
void Push(LinkedList L,int X)
{
LinkedList Tmp = L;
while (Tmp->Next != NULL)
Tmp = Tmp->Next;
LinkedList Node = new LinkedListNode;
Node->Element = X;
Node->Next = NULL;
Tmp->Next = Node;
NodeNumber++;
}
int Pop(LinkedList L)
{
if (IsEmpty(L))
{
cout << "Empty Stack!" << endl;
return 0;
}
LinkedList End=L->Next;
while (End->Next != NULL)
End = End->Next;
LinkedList Pre = L;
while (Pre->Next->Next != NULL)
Pre = Pre->Next;
Pre->Next = NULL;
int Ret = End->Element;
delete End;
NodeNumber--;
return Ret;
}
int GetNodeNumber()
{
return NodeNumber;
}
void Show(LinkedList L)
{
if (IsEmpty(L))
{
cout << "Empty Stack!" << endl;
return ;
}
LinkedList P = L->Next;
while (P != NULL)
{
cout << P->Element <<endl;
P = P->Next;
}
}
LinkedList Reverse(LinkedList L,int K)//K>=1且K不大于栈中节点数
{
if (IsEmpty(L))
{
cout << "Empty Stack!" << endl;
return L;
}
if (K == 1)//如果K为1,则直接返回L
return L;
LinkedList New = Initialize();
LinkedList Tmp = L->Next,P=New;
LinkedList Head, Rail;
while (1)
{
Head = Tmp;
for (int i = 0; i < K-1; i++)
{
if (Tmp == NULL)//如果N是K的倍数,则返回New
return New;
else if (Tmp->Next != NULL)
Tmp = Tmp->Next;
else//如果N不是K的倍数,则继续把链表最后面不到K个节点复制到链表New中,再返回New
{
while (Head != NULL)
{
Push(New, Head->Element);
Head = Head->Next;
}
return New;
}
}
Push(New, Tmp->Element);
Tmp = Tmp->Next;
for (int i = K-1; i >0; i--)
{
Rail = Head;
for (int j = 0; j < i - 1; j++)
Rail = Rail->Next;
Push(New, Rail->Element);
}
}
}
};
int main()
{
int N, K;
cin >> N >> K;
int *arr = new int[N];
for (int i = 0; i < N; i++)
cin >> arr[i];
Stack LL;
LinkedList L = LL.Initialize();
for (int i = 0; i < N; i++)
LL.Push(L,arr[i]);
LinkedList New = LL.Reverse(L, K);
LL.Show(New);
return 0;
}