zoukankan      html  css  js  c++  java
  • 链表反转【图解】

    给出一个链表的头结点,将链表反转后返回新的头结点

    首先假设该链表头结点【pHead】在左边,尾节点在右边
    设定三个指针:tmp 、p、q
    其中tmp和q两个指针将不断向后移动,而p指针则定在原头结点位置不动,但其next将不断跟着tmp和q指针移动。

    tmp      q
     @   ——> @  ——> @  ——> @  ——> @   初始状态
     p
    

    第一步我们改变p指针的Next,使其指向p的next,并将q指针的next反转到tmp上

    tmp     q
      /```````````
     @  <—— @      @  ——> @  ——> @   第一步
     p
    

    第二步将tmp指针移动到q指针的位置,并将q指针移动到p->next的位置

           tmp     q
      /```````````
     @  <—— @      @  ——> @  ——> @   第二步
     p
    

    此时我们发现已经出现了初始状态的情况,重复做第一步
    继续将p->next指向q->next,并反转q->next的指针到tmp上

           tmp     q
      /``````````````````
     @ <——  @ <——  @      @  ——> @   第一步
     p
    

    继续将tmp和q指针向后移动,相当于重复做第二步

                  tmp     q
      /``````````````````
     @ <——  @ <——  @      @  ——> @   第二步
     p
    

    重复第一步

                 tmp     q
      /`````````````````````````
     @ <——  @ <—— @ <——  @       @   第一步
     p
    

    继续将tmp指针和q指针后移

                        tmp      q
      /`````````````````````````
     @ <——  @ <—— @ <——  @       @   第二步
     p
    

    此时发现,我们已经将p指针挪到了链表尾部,q->next为空,那么正好将p直接指向q的next,使其为NULL,由原头结点变为尾节点,而因为q指针指向节点的next反转到tmp上,最后一个节点的指针也反转过来了,新的头结点诞生。
    而因为q不能继续后移到空指针上,因此while循环退出,tmp正常后移到q节点上,返回tmp指针即反转后的头结点指针。【此处明明tmp和q指针指向相同的位置,为什么返回的是tmp指针? 因为在链表只有一个节点时,q是空指针,而tmp是头结点,那么反映了一种情况即,只有一个节点,头结点即尾节点,反转后不变,循环不进入,直接返回初始tmp,也就是头结点,而q指针就不同了,其指向的是空指针,从未指向头结点,因此不能返回q指针而应返回tmp】

    NULL                       tmp
     ↑                          q
     @ <——  @ <—— @ <——  @  <—— @   第二步
     p
    

    代码如下:

    /*
    struct ListNode {
    	int val;
    	struct ListNode *next;
    	ListNode(int x) :
    			val(x), next(NULL) {
    	}
    };*/
    class Solution {
    public:
        ListNode* ReverseList(ListNode* pHead) {
            if(pHead==NULL)return pHead;
            ListNode* p=pHead;
            ListNode* q=pHead->next;
            ListNode* tmp=pHead;
            while(p->next!=NULL)
            {
                p->next=q->next;
                q->next=tmp;
                tmp=q;
                if(p->next==NULL)break;
                q=p->next;
            }
            return tmp;
        }
    };
    

    另一种写法,最普遍的三指针法。也是很好理解的:
    当前结点的下一个即pNext
    当前结点的前一个即pPrev
    当前结点即pNode
    将当前结点的下一个存下来,判断是否为空,则可知当前结点是不是翻转后链表的首节点
    将当前节点的m_pNext指针指向上一个节点pPrev,将上一个节点指针指向后挪到当前结点,将当前结点指针指向下一个结点,重复以上步骤

    ListNode* ReverseList(ListNode* pHead)
    {
        ListNode* pRevesedHead=nullptr;
        ListNode* pNode=pHead;
        ListNode* pPrev=nullptr;
        while(pNode!=nullptr)
        {
            ListNode* pNext=pNode->m_pNext;
            if(pNext==nullptr)pRevesedHead=pNode;
            pNode->m_pNext=pPrev;
            pPrev=pNode;
            pNode=pNext;
        }
        return pRevesedHead;
    }
    
  • 相关阅读:
    [Agc081F/At2699] Flip and Rectangles
    [CF1216C] White Sheet
    stegsolve使用探究
    栅栏密码
    wireshark常用命令
    某团队线下赛AWD writeup&Beescms_V4.0代码审计
    某线下赛AWD
    BBScan — 一个信息泄漏批量扫描脚本
    ISG2018 web题Writeup
    巅峰极客第二场CTF部分writeup
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135680.html
Copyright © 2011-2022 走看看