单链表翻转

一、节点的定义

struct ListNode{  
    int val;  
    ListNode* next;  
    ListNode(int a):val(a),next(NULL){}  
};  

二、 翻转的方法

1、迭代

  1. 在遍历列表时,我们需要将当前节点的 next 指针改为指向前一个元素
  2. 前一个元素没有,所以要先存储其前一个元素
  3. 在更改引用之前,还需要另一个指针来存储后一个节点

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next; // 存储当前节点的下一个节点
            curr->next = prev; // 更改当前节点指向的元素
            prev = curr;  //当前节点赋值给前一个节点
            curr = next; // 下个节点赋值给当前节点
        }
        return prev;
    }
};

注意,在反转链表时要先确定一个pre节点,表示当前节点的前一个节点。初始时pre为空指针。在循环中,需要先将下一个节点next保存下来,以便于后续操作,然后将当前节点的next指向pre,反转当前节点。之后要更新pre和cur,使得下一次循环可以正确进行。循环一直进行到cur为nullptr,此时链表就被反转了。 

2、就地反转法

把当前链表的下一个节点pCur插入到头结点dummy的下一个节点中,就地反转。

dummy->1->2->3->4->5的就地反转过程:

dummy->2->1->3->4->5

dummy->3->2->1->4->5

dummy->4>-3->2->1->5

dummy->5->4->3->2->1

过程:

  1. prev连接下一次需要反转的节点
  2. 反转节点pCur
  3. 纠正头结点dummy的指向
  4. pCur指向下一次要反转的节点

class Solution {
public:
    ListNode *reverseList(ListNode *head)
    {
         if (head == nullptr)
            return head;
        ListNode dummy = ListNode(-1);
        dummy.next = head;
        ListNode* pre = head; // 前一个要反转的节点
        ListNode* cur = head->next; // 当前要反转的节点
        while (cur) {
            pre->next = cur->next;
            cur->next = dummy.next;
            dummy.next=cur;
            cur=pre->next;
        }
       return dummy.next;
    }
};

3、递归

  • 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 ret .
  • 此后,每次函数在返回的过程中,让当前结点的下一个结点的 next 指针指向当前节点。
  • 同时让当前结点的 next 指针指向 NULL ,从而实现从链表尾部开始的局部反转
  • 当递归函数全部出栈后,链表反转完成。

递归解题首先要做的是明确递推公式的含义,在这里对于结点1来说,它只需要知道它之后的所有节点反转之后的结果就可以了,也就是说递推公式reverseList的含义是:把拿到的链表进行反转,然后返回新的头结点。

 到这里,就可以写成如下的代码了。

ListNode* reverseList(ListNode* head) {
    // 调用递推公式反转当前结点之后的所有节点
    // 返回的结果是反转后的链表的头结点
    ListNode* newHead = reverseList(head->next);
}

 接着要做的就是反转结点1,也就是将head指向的结点作为其下一个结点的下一个结点,即head.next.next=head。

最后,将head指向的结点的下一个结点置为nullptr,就完成了整个链表的反转。

 代码如下

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr || head->next == nullptr ) {
            return head;
        }
        ListNode* ret = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr ; // 因为此时的head,最终是新链表的尾部,所以要让它指向Null
        return ret;
    }
};

 参考:

单链表反转总结篇 - mao的博客 - 博客园

看图理解单链表的反转 - ma_fighting - 博客园

https://labuladong.gitee.io/algo/2/17/16/

力扣

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值