针对数据结构02线性表——反转链表(拓展)在头歌平台练习过程中的完成代码,每题思路单独在每一关中解释。如有其他需求请留言.
第一关
已知一个带头结点的单链表L,将L反转并返回反转后的单链表。要求将L的结点空间进行反转,而不仅仅是修改每个结点的值。
对于反转链表的操作,作者习惯使用头插法来实现,主要步骤如下:
1.先把设置两个指针,一个指向头节点,另一个指向头节点的下一个节点。
2.将头节点的指针域设置成空,变成一个空链表。
3.另一个指针遍历链表,每个节点用在链表头插入的方法插入新的空链表。
void ReverseList(LinkList L) {
/*--------------代码开始----------------*/
LinkList c = L;
LinkList p = L -> next;
c -> next = NULL;
while(p != NULL)
{
LinkList q = p;
p = p -> next;
q ->next = c -> next;
c -> next = q;
}
/*--------------代码结束----------------*/
}
第二关
已知一个带头结点的单链表L,每k个结点一组进行反转,返回反转后的单链表。 k是一个正整数,它的值小于或等于L的长度。如果L中结点总数不是k的整数倍,那么请将最后剩余的结点保持原有顺序。 要求将L的结点空间进行反转,而不仅仅是修改每个结点的值。
我们先思考对于一个长度位k的区间进行反转,对于整个链表逆置时,我们操作的区间相当于是对长度1-length的区间操作,所以我们对某个长度为k的区间操作时只需要改变区间的长度,原理一样,把区间第一个节点的前一个节点看成头节点,最后一个节点看作尾节点,用指针来记录即可。
和第一关的操作一样,先把该区间从链表上取下来,然后依次采用头插法,头节点即是我们每次递归传递的节点。
同时可以观察到,每个区间的第一个节点逆置之后相当于下一个连续区间的头节点,我们把那个节点标记下来,当我们完整对目前区间的操作后,用递归的思想往后递归。
递归的终止条件就是剩余节点数目小于k,注意判断的位置否则可能陷入死循环。
void ReverseKGroup(LinkList L,int k) {
/*--------------代码开始----------------*/
if(k == 1) return ;
LinkList a = L;
LinkList q = L -> next;
LinkList p = L -> next;
for(int i = 1 ; i < k ; i ++)
{
if(p == NULL) return ;
p = p -> next;
if(p == NULL) return ;
}
LinkList c = a -> next;
a -> next = p ->next;
p -> next = NULL;
while(q != NULL)
{
LinkList t = q;
q = q -> next;
t -> next = a -> next;
a -> next = t;
}
ReverseKGroup(c,k);
return ;
/*--------------代码结束----------------*/
}