题目:
链表翻转。给出一个链表和一个数k,比如链表1→2→3→4→5→6,k=2,翻转后2→1→4→3→6→5,若k=3,翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→5→6,用程序实现Node* RotateList(Node* list, size_t k).
思路:
这道题我的解决方式是分俩步解决它。
第一步先把链表划为多个小链表,每个小链表长度为K。先把每个小链表完成逆置。
第二步把每个小链表的尾首相连起来。
如图:
细节问题
K对于链表来说分俩种情况:
第一种就是链表大小刚好够分成大小为K的几个小链表。
第二种就是链表大小不足以刚好划分为大小为K的小链表,即第一个小链表可能够分,但是到了第二个的时候剩余的节点不够划分为大小为K的小链表了,上图就是这俩种情况。
所以对于第一种刚好够分,start end 这俩个界限的指针最终都走向NULL,对于不够分start最终非NULL。
那么我们就要最后把start入Phead队列,以便上一链表的尾连向它。
代码
Node* RotateList(Node* list, size_t k)
{
assert(list != NULL&&k > 0);
if (list->_PNext == NULL)
{
if (k > 1) {
cerr << "k值大于链表长度" << endl;
exit(1);
}
return list;
}
queue<Node*> qhead;
queue<Node*> qtail;
Node*start = list;
Node*end = start;//尾随位置
Node*ppre = list;
Node*pCur = ppre->_PNext;
Node*Next = pCur->_PNext;
int step = k;
while (end!=NULL&&step-- > 0)
{
end = end->_PNext;
}
if (end == NULL)
{
cerr << "k值大于链表长度" << endl;
exit(1);
}
step = k;
while (start != NULL)
{
qtail.push(ppre);
while (pCur!=NULL)
{
pCur->_PNext = ppre;
ppre = pCur;
pCur = Next;
if(Next!=NULL)Next = Next->_PNext;
if (ppre==end||pCur == end) break;
}
if (pCur == end)
{
qhead.push(ppre);
}
start = end;
if (end == NULL) break;//能进来end肯定不为空
ppre = end;
pCur = ppre->_PNext;//end不为空,但pCur是end的下一个,它有可能为空
if (pCur != NULL)Next = pCur->_PNext;
step = k;
while (end != NULL&&step-- > 0)
{
end = end->_PNext;
}
if (step>0) break;
}
if(start!=NULL)qhead.push(start);//说明长度没正好够走完。
Node*ret = qhead.front();
qhead.pop();
Node*phead = NULL;
Node*ptail = NULL;
while (!qhead.empty())
{
ptail= qtail.front();
qtail.pop();
phead = qhead.front();
qhead.pop();
ptail->_PNext = phead;
}
if (!qtail.empty())//到这分俩种情况 第一种 整个链表长度刚好够分几个小块 ,这时qtail内还剩下最后一个节点.
{ //第二种如果不够分几个小块,也就是说end不是正好走到NULL而是因为链表长度不够了走到NULL的时候K还大于0,此时qtail走到这里为空
ptail = qtail.front();
ptail->_PNext = NULL;
}
return ret;
}