PTA(链表)1-10 单链表分段逆转
PTA(链表)1-10 单链表分段逆转
zhangzhang1-10 单链表分段逆转
分数 6
作者 陈越
单位 浙江大学
给定一个带头结点的单链表和一个整数K,要求你将链表中的每K个结点做一次逆转。例如给定单链表 1→2→3→4→5→6 和 K=3,你需要将链表改造成 3→2→1→6→5→4;如果 K=4,则应该得到 4→3→2→1→5→6。
函数接口定义:
1 | void K_Reverse( List L, int K ); |
其中List结构定义如下:
1 | typedef struct Node *PtrToNode; |
L是给定的带头结点的单链表,K是每段的长度。函数K_Reverse应将L中的结点按要求分段逆转。
裁判测试程序样例:
1 |
|
输入样例:
1 | 6 |
输出样例:
1 | 4 3 2 1 5 6 |
解析
此题依旧是一头雾水,如果单链表的逆转(用到三指针)不会的话先去看看PTA(链表)1-2 单链表逆转 | zhangzhang-blog
此题是在这个的基础上的
1 | void K_Reverse( List L, int K ) |
示意图
1.初始状态
2.跟单链表的逆转一样了(三指针)
K=3,i=0时如下图
K=3,i=1时如下图
K=3,i=2时如下图
PreTail->Next = prev;
算法思路
- 分段遍历与定位: 使用一个指针
PreTail始终指向当前段逆转前的头结点(即上一段的尾结点或整个链表的头结点)。初始时,PreTail指向链表的头结点 $L$。 - 检查段长: 在开始逆转一段之前,先从
PreTail->Next开始向后检查 $K$ 个结点是否存在。如果不存在 $K$ 个结点,则这段不进行逆转,直接退出循环。 - 定位段的头部和尾部:
NewTail: 逆转后新段的尾结点,即逆转前老段的头结点PreTail->Next。Current: 用于遍历 $K$ 个结点,并辅助逆转操作。NextHead: 逆转后新段的头结点(即逆转前老段的第 $K$ 个结点)。
- $K$ 个结点的原地逆转:
- 逆转操作在 $K$ 个结点内部进行。我们采用头插法的思想进行原地逆转,或者使用三个指针 (
prev,curr,next) 的标准链表逆转方法。 - 这里我们采用标准逆转法:
prev初始化为nullptr(或NULL)。curr初始化为NewTail。- 循环 $K$ 次,将
curr的Next指针指向prev,然后更新prev和curr。
- 逆转操作在 $K$ 个结点内部进行。我们采用头插法的思想进行原地逆转,或者使用三个指针 (
- 连接新的段:
- 逆转完成后,
prev将指向逆转后的新段的头结点NextHead。(这样下一次curr->next = prev,可以让此次尾部连接下一次的反转的头部) NewTail(逆转前的头结点)现在是逆转后的尾结点,它的Next应该连接到下一段的头结点。这个下一段的头结点就是逆转开始前Current(循环 $K$ 次后的下一个结点)。PreTail(上一段的尾结点)的Next应该指向逆转后的新段的头结点NextHead(prev)。- 更新
PreTail指向新逆转段的尾结点,即NewTail,以便开始下一段的逆转。
- 逆转完成后,
做题:先定义Pretail,判断是否满足K个,不满足就退出,再定义NewTail,Current,NextHead,这是找此次反转的头部和尾部,再就是反转该链表,用的是三指针法







