栈实现链表反转c语言,C语言实现反转链表 II(指定2个节点反转)

要求:

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:

1 ≤ m ≤ n ≤ 链表长度。

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4

输出: 1->4->3->2->5->NULL

方法迭代链接反转

算法

在看具体算法之前,有必要先弄清楚链接反转的原理以及需要哪些指针。举例而言,有一个三个不同结点组成的链表 A → B → C,需要反转结点中的链接成为 A ← B ← C。

假设我们有两个指针,一个指向结点 A,一个指向结点 B。 分别记为 prev 和 cur。则可以用这两个指针简单地实现 A 和 B 之间的链接反转:

cur.next = prev

这样做唯一的问题是,没有办法继续下去,换而言之,这样做之后就无法再访问到结点 C。因此,我们需要引入第三个指针,用于帮助反转过程的进行。因此,我们不采用上面的反转方法,而是:

third = cur.next

cur.next = prev

prev = cur

cur = third

迭代 地进行上述过程,即可完成问题的要求。下面来看看算法的步骤。

1.如上所述,我们需要两个指针 prev 和 cur。

2.prev 指针初始化为 None,cur 指针初始化为链表的 head。

3.一步步地向前推进 cur 指针,prev 指针跟随其后。

4.如此推进两个指针,直到 cur 指针到达从链表头起的第 mm 个结点。这就是我们反转链表的起始位置。

5.注意我们要引入两个额外指针,分别称为 tail 和 con。tail 指针指向从链表头起的第mm个结点,此结点是反转后链表的尾部,故称为 tail。con 指针指向第 mm 个结点的前一个结点,此结点是新链表的头部。下图可以帮助你更好的理解这两个指针。

e77660f94208e2787ba5d36b588a8fb2.png

6.tail 和 con 指针在算法开始时被初始化,在算法最后被调用,用于完成链表反转。

7.如前文所解释的那样,抵达第 mm 个结点后,在用到上述两个指针前,先迭代地反转链接。不断迭代,直到完成指向第 nn 个结点的链接。此时,prev 指针会指向第 nn 个结点。

8.我们使用 con 指针来连接 prev 指针,这是因为 prev 指针当前指向的结点(第 nn 个结点)会代替第 mm 个结点的位置。 类似地,我们利用 tail 指针来连接 prev 指针之后的结点(第 n+1n+1 个结点)。

为了便于理清每个指针的用法,我们来看一个算法运行的实例。给定一个链表 7 → 9 → 2 → 10 → 1 → 8 → 6,我们需要反转从第 3 个结点到第 6 个结点的子链表

8dc13f45732a212807b33fbd59f3932d.png

从上图可以看到迭代法的前几步。第一步展示了两个指针的初始化,第三步展示了链表反转过程的初始位置。

51020503814e73a5603f3aec263b0118.png

上图详细显示了链接反转的过程以及反转两个结点的链接后如何向前移动。如下图所示,本步骤将执行多次。

4e13c1d1eccd24fa2b43e475e024c4ab.png

如上图所示, 两个指针都已经到达最终位置。我们完成了子链表的反转工作。然而,还有一些链接需要调整。下图展示了利用 tail 和 con 指针完成链接调整的过程。

3003b415211f4957432cbc05a676ca86.png

以上链接:https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/fan-zhuan-lian-biao-ii-by-leetcode/

Definition for singly-linked list.

* struct ListNode {

*     int val;

*     struct ListNode *next;

* };

*/

typedef struct ListNode * PNODE ;

typedef struct ListNode NODE ;

struct ListNode* reverseBetween(struct ListNode* phead, int m, int n){

PNODE prev=NULL ;

PNODE curr=phead;

PNODE temp=NULL ;

PNODE con =NULL ;

PNODE tail=NULL ;

if(phead==NULL)

{

return NULL ;

}

while(m>1)

{

prev=curr;

curr=curr->next;

m-- ;

n-- ;

}

con=prev ;

tail=curr ;

while(n>0)

{

temp=curr->next;

curr->next=prev;

prev=curr;

curr=temp;

n--;

}

//调整算法连接

if(con!=NULL)

{

con->next=prev ;

}

else

{

phead=prev ;

}

tail->next=curr ;

return phead ;

}

原文:https://www.cnblogs.com/cocobear9/p/12370081.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值