题目:
给定一个链表,实现一个函数,将链表中每k个节点进行翻转,若最后一组节点数量不足k个,则按实际个数翻转。例如:给定链表1->2->3->4->5->6->7->8->NULL,k=3,翻转后输出3->2->1->6->5->4->8->7->NULL。
翻转函数reverse有两个参数,分别为链表头指针和翻转步长k。输入:
输入的第一行指定用例数量T;
用例的第一行输入指定链表节点个数N;
用例的第二行输入指定N个节点数值,使用空格隔开;
用例的第三行输入指定翻转步长K;
输出:
按照K翻转后的链表节点值
例如:
Input:
1
8
1 2 2 4 5 6 7 8
4
Output:
4 2 2 1 8 7 6 5
解题思路:
调用我之前写过的单链表数据结构来搭建链表:数据结构-单链表-C++模板实现
有关题目翻转的操作放在List类reverse()函数中,大概思路是指针指向需要翻转的头和尾,调换头尾的顺序,然后头指针++,尾指针--,直到头>尾表示这段已经翻转完毕,具体解释代码中有。
#include <iostream>
using namespace std;
template<class T>
class Node
{
public:
T data;
Node<T> * next;
Node() :next(NULL) {}
Node(T value) :next(NULL), data(value) {}
~Node() {}
friend ostream& operator<<(ostream &os, const Node<T> *node)
{
os << node->data;
return os;
}
};
template<class T>
class List
{
public:
List()
{
m_pList = new Node<T>;
m_iLength = 0;
}
~List()
{
ClearList();
delete m_pList;
}
void ClearList()
{
for (int i = 0; i<m_iLength; i++)
ListDelete(i);
m_pList->next = NULL;
m_iLength = 0;
}
bool ListEmpty()
{
return !m_iLength;
}
int ListLength()
{
return m_iLength;
}
bool ListInsert(int i, T value)//将value插入第i个节点之前
{
if (i<0 || i>m_iLength) return false;
//先找到需要插入的i节点之前的节点currentNodeBefore
Node<T> *currentNodeBefore = m_pList;
for (int k = 0; k<i; k++)
currentNodeBefore = currentNodeBefore->next;
//new一个Node
Node<T> * newNode = new Node<T>(value);
//将newNode插入currentNodeBefore之后,即为插入i节点前
newNode->next = currentNodeBefore->next;
currentNodeBefore->next = newNode;
m_iLength++;
return true;
}
bool ListDelete(int i)//删除第i个节点
{
if (i<0 || i >= m_iLength) return false;
//找到需要删除节点的前一个节点
Node<T> *currentNodeBefore = m_pList;
for (int k = 0; k < i; k++)
currentNodeBefore = currentNodeBefore->next;
//定位currentNode,删除操作
Node<T> *currentNode = currentNodeBefore->next;
currentNodeBefore->next = currentNodeBefore->next->next;
delete currentNode;
m_iLength--;
return true;
}
bool ListInsertTail(T value)
{
//new一个Node,将newNode->next置为NULL
Node<T> *newNode = new Node<T>(value);
//找到尾节点currentNode
Node<T> *currentNode = m_pList;
while (currentNode->next != NULL)
currentNode = currentNode->next;
//将newNode连接上尾节点currentNode
currentNode->next = newNode;
m_iLength++;
if (newNode->next == NULL)
return true;
else return false;
}
T& GetElem(int i)//返回第i节点数据
{
Node<T> *currentNode = m_pList->next;
for (int k = 0; k < i; k++)
currentNode = currentNode->next;
return currentNode->data;
}
void reverse(int k)
{
int reverseTime = m_iLength / k;//翻转的整段数,eg:1 2 3 4 5 6 7 8,k=3,则123为一段,456为一段,需要翻转的整段数为2
int pre = 0;//用来指向需要翻转段的头节点,闭区间
int cur = k - 1;//用来指向需要翻转段的尾节点,闭区间
//处理整段的翻转
for (int i = 0; i < reverseTime; i++)
{
int ppre = pre;
int pcur = cur;
while (ppre < pcur)
{
int preData = GetElem(ppre);
int curData = GetElem(pcur);
ListDelete(pcur);
ListInsert(pcur, preData);
ListDelete(ppre);
ListInsert(ppre, curData);
ppre++;
pcur--;
}
pre += k;
cur += k;
}
//当整段翻转完毕,pre指向下一段的开头,cur肯定超出边界,所以将cur拉回至末尾元素
while (cur >= m_iLength)
cur--;
//当整段翻转完成后恰好到末尾,后面没有需要翻转的元素了,则退出
if (pre >= cur)
return;
//处理尾端不完整段的翻转
while (pre < cur)
{
int preData = GetElem(pre);
int curData = GetElem(cur);
ListDelete(cur);
ListInsert(cur, preData);
ListDelete(pre);
ListInsert(pre, curData);
pre++;
cur--;
}
}
void ListTraverse()
{
Node<T> *currentNode = m_pList->next;
while (currentNode != NULL)
{
cout << currentNode << " ";
currentNode = currentNode->next;
}
cout << endl;
}
public:
Node<T> *m_pList;
int m_iLength;
};
int main()
{
int t;
cin >> t;
while (t--)
{
int listSize;
cin >> listSize;
List<int> list;
for (int i = 0; i < listSize; i++)
{
int node;
cin >> node;
list.ListInsertTail(node);
}
int reverseNum;
cin >> reverseNum;
list.reverse(reverseNum);
list.ListTraverse();
}
return 0;
}
本文介绍了一种算法,该算法能够实现链表中每K个节点的翻转操作,包括不足K个节点的最后一组。通过定义一个List类,并在其中实现reverse函数,可以有效地完成这一任务。

被折叠的 条评论
为什么被折叠?



