單鏈表反轉(zhuǎn)

參考:https://blog.csdn.net/superxiaolong123/article/details/86687733

首先要了解一個(gè)鏈表節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu):


在這里插入圖片描述

value代表該節(jié)點(diǎn)存儲(chǔ)的值,next指向下一個(gè)節(jié)點(diǎn)浦旱,next可能指向一個(gè)單一節(jié)點(diǎn)杉适,也可能指向一個(gè)鏈表蝴蜓,也可能指向null(代表尾節(jié)點(diǎn))。

方法一:頭節(jié)點(diǎn)插入法(推薦)
實(shí)現(xiàn)步驟:

  1. 創(chuàng)建一個(gè)帶頭節(jié)點(diǎn)的鏈表resultList
  2. 定義一個(gè)循環(huán)鏈表變量p,p的初始值為待反轉(zhuǎn)的鏈表
  3. 遍歷待反轉(zhuǎn)的鏈表挡闰,遍歷條件為 (p !=null)
    3.1 定義一個(gè)臨時(shí)鏈表變量tempList保存p->next的值(因?yàn)閜->next值會(huì)改變)头岔,用于下一次循環(huán)。
    3.2 把p當(dāng)前指向的首節(jié)點(diǎn)和resultList鏈表的頭節(jié)點(diǎn)之后的節(jié)點(diǎn)拼接起來劲赠。(resultlist.next其實(shí)=null,相當(dāng)于把插入節(jié)點(diǎn)的next置為null涛目,等價(jià)于p.next = null)
    3.3 把3.2步驟中拼接的節(jié)點(diǎn) 再拼接到resultList頭節(jié)點(diǎn)后。
    3.4 p重新賦值為3.1步驟中保存的tempList的值凛澎。
  4. 返回resultList->next.即反轉(zhuǎn)后的鏈表泌绣。

圖解:

在這里插入圖片描述

圖1就是待反轉(zhuǎn)的原始鏈表,圖2是 帶頭節(jié)點(diǎn)的鏈表resultList预厌。
可以看到p是一個(gè)循環(huán)變量阿迈,初始值指向待反轉(zhuǎn)的原始鏈表。
通過p變量遍歷鏈表轧叽,在遍歷中(列舉的值為第一次循環(huán)的情況):

  • 定義一個(gè)臨時(shí)鏈表變量tempList保存p->next的值苗沧,tempList指向圖1.2
  • 把p當(dāng)前指向的首節(jié)點(diǎn)(圖1.1)和resultList鏈表的頭節(jié)點(diǎn)之后的節(jié)點(diǎn)(圖2.2)拼接起來。
  • 把3.2步驟中拼接的節(jié)點(diǎn)(圖3.2) 再拼接到resultList頭節(jié)點(diǎn)后炭晒。
  • p重新賦值為3.1步驟中保存的tempList的值待逞,即圖1.2。

最后返回resultList->next网严,也就是去除了頭節(jié)點(diǎn)-1的值识樱。

通過頭結(jié)點(diǎn)插入法實(shí)現(xiàn)鏈表反轉(zhuǎn)功能,主要難點(diǎn)就是在循環(huán)中的3.2和3.3步驟的理解。
需要注意的是怜庸,就是關(guān)注循環(huán)變量p的值当犯,也就是指向的變化,傳統(tǒng)的遍歷過程就是條件為p!=null,處理,p=p->next割疾。但是在這個(gè)頭結(jié)點(diǎn)插入代碼中嚎卫,p->next的值發(fā)生的變化,因?yàn)橐獙esultList結(jié)果鏈表的內(nèi)容拼接到p的首節(jié)點(diǎn)后宏榕,所以要定義一個(gè)臨時(shí)變量存p->next拓诸。

    public static ListNode reverseListByInsert(ListNode listNode){
        //定義一個(gè)帶頭節(jié)點(diǎn)的
        ListNode resultList = new ListNode(-1);
        //循環(huán)節(jié)點(diǎn)
        ListNode p = listNode;
        while(p!= null){
            //保存插入點(diǎn)之后的數(shù)據(jù)
            ListNode tempList = p.next;
            p.next = resultList.next;//連接頭節(jié)點(diǎn)和下一個(gè)節(jié)點(diǎn)(參照頭插法圖)
            resultList.next = p;
            p = tempList;
        }
        return resultList.next;
    }

邏輯參考2

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

ListNode* reverseList(ListNode* head) {
    ListNode *phead=new ListNode(-1);//注意第6行l(wèi)istNode(int x)中括號(hào)要寫值,這里隨便寫麻昼,因?yàn)轭^節(jié)點(diǎn)的val不重要
    phead->next=NULL;//申請一個(gè)頭節(jié)點(diǎn)奠支,在空結(jié)點(diǎn)后插入值
    ListNode *ptemp;//臨時(shí)結(jié)點(diǎn),存放插入的值
    ListNode *t;//控制插入節(jié)點(diǎn)的值
    t=head;//從第一個(gè)結(jié)點(diǎn)開始
    while(t!=NULL){
    ptemp=t;
    t=t->next;
    ptemp->next=phead->next;//phead->next第一次其實(shí)=null
    phead->next=ptemp;
    }
    return phead->next;
  }

方法二:就地反轉(zhuǎn)1
頭結(jié)點(diǎn)插入法的實(shí)質(zhì)是重新創(chuàng)建了一個(gè)新的鏈表抚芦,通過遍歷待反轉(zhuǎn)鏈表胚宦,將鏈表每一個(gè)節(jié)點(diǎn)插入到創(chuàng)建的鏈表中,然后的到的這個(gè)創(chuàng)建的鏈表就是反轉(zhuǎn)后的鏈表燕垃。而就地反轉(zhuǎn)實(shí)質(zhì)就是在待反轉(zhuǎn)鏈表基礎(chǔ)上修改節(jié)點(diǎn)順序得到反轉(zhuǎn)鏈表枢劝。所以原理還是不同的。

圖解:

在這里插入圖片描述

個(gè)人認(rèn)為就地反轉(zhuǎn)比頭結(jié)點(diǎn)插入稍微難理解一點(diǎn)卜壕。
宏觀上來看您旁,要實(shí)現(xiàn)節(jié)點(diǎn)1和節(jié)點(diǎn)2反轉(zhuǎn),需要將節(jié)點(diǎn)1插入節(jié)點(diǎn)2和節(jié)點(diǎn)3當(dāng)中轴捎,然后將頭節(jié)點(diǎn)為2的鏈表插入結(jié)果鏈表頭結(jié)點(diǎn)后面鹤盒,然后再后移一個(gè)節(jié)點(diǎn)做同樣的操作。
然而涉及到兩個(gè)節(jié)點(diǎn)的循環(huán)賦值侦副,這個(gè)操作順序就比較重要了侦锯。
正確的步驟是先將節(jié)點(diǎn)2切分出來,再將節(jié)點(diǎn)2插入-1和1之間秦驯。

實(shí)現(xiàn)步驟

  1. 創(chuàng)建一個(gè)帶頭節(jié)點(diǎn)的鏈表resultList尺碰,頭結(jié)點(diǎn)指向待反轉(zhuǎn)的鏈表。
  2. 創(chuàng)建p译隘、pNext兩個(gè)用于循環(huán)操作亲桥,分別指向兩個(gè)待反轉(zhuǎn)節(jié)點(diǎn)的位置,初始值如圖所示,指向1和2
  3. 遍歷帶反轉(zhuǎn)的鏈表固耘,循環(huán)條件是pNext!=null.
    3.1 從鏈表中分割出pNext節(jié)點(diǎn)题篷,也就是讓p指向pNext->next。
    3.2 讓pNext指向經(jīng)過3.1操作之后的resultList.next(1->3->4->5)
    3.3 讓resultList頭結(jié)點(diǎn)指向pNext(2->1->3->4->5)
    3.4 讓pNext指向p的下一個(gè)節(jié)點(diǎn)
    難點(diǎn)在于理解循環(huán)中resultList.next指向性的變化厅目,以及p和pNext兩個(gè)變量的變化番枚,p指向的鏈表首結(jié)點(diǎn)永遠(yuǎn)是1,只是節(jié)點(diǎn)1在resultList鏈表中位置在發(fā)生變化法严,而pNext是隨著p移動(dòng)的,腦子中間可以有一個(gè)擺繩模型葫笼,在起始點(diǎn)位置發(fā)力深啤,繩子的高點(diǎn)位置會(huì)移到繩尾,那個(gè)最高點(diǎn)就是p變量位置渔欢。
public static ListNode reverseListByLocal(ListNode listNode){
        ListNode resultList = new ListNode(-1);
        resultList.next= listNode;
        ListNode p = listNode;
        ListNode pNext = p.next;
        while (pNext!=null){
            p.next = pNext.next;
            pNext.next = resultList.next;
            resultList.next = pNext;
            pNext=p.next;
        }
        return resultList.next;
    }

頭插法分析圖:

image.png

方法二:就地反轉(zhuǎn)2(推薦)

參考:https://www.cnblogs.com/byrhuangqiang/p/4311336.html

2.1 思路

把當(dāng)前鏈表的下一個(gè)節(jié)點(diǎn)pCur插入到頭結(jié)點(diǎn)dummy的下一個(gè)節(jié)點(diǎn)中,就地反轉(zhuǎn)瘟忱。

dummy->1->2->3->4->5的就地反轉(zhuǎn)過程:
dummy->2->1->3->4->5
dummy->3->2->1->4->5
dummy->4>-3->2->1->5
dummy->5->4->3->2->1

2.2 解釋

1初始狀態(tài)

image

2 過程

pCur是需要反轉(zhuǎn)的節(jié)點(diǎn)奥额。

  1. prev連接下一次需要反轉(zhuǎn)的節(jié)點(diǎn)
  2. 反轉(zhuǎn)節(jié)點(diǎn)pCur
  3. 糾正頭結(jié)點(diǎn)dummy的指向
  4. pCur指向下一次要反轉(zhuǎn)的節(jié)點(diǎn)

偽代碼

1 prev.next = pCur.next;
2 pCur.next = dummy.next;
3 dummy.next = pCur;
4 pCur = prev.next;

image

3 循環(huán)條件

pCur is not null

2.3 代碼

// 1.就地反轉(zhuǎn)法
    public ListNode reverseList1(ListNode head) {
        if (head == null)
            return head;
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode prev =head;//修改了原文的dummy.next 
        ListNode pCur = prev.next;
        while (pCur != null) {
            prev.next = pCur.next;
            pCur.next = dummy.next;
            dummy.next = pCur;
            pCur = prev.next;
        }
        return dummy.next;
    }

2.4 總結(jié)

  • 1個(gè)頭結(jié)點(diǎn),2個(gè)指針访诱,4行代碼
  • 注意初始狀態(tài)和結(jié)束狀態(tài)垫挨,體會(huì)中間的圖解過程。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末触菜,一起剝皮案震驚了整個(gè)濱河市九榔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涡相,老刑警劉巖哲泊,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異催蝗,居然都是意外死亡切威,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門丙号,熙熙樓的掌柜王于貴愁眉苦臉地迎上來先朦,“玉大人,你說我怎么就攤上這事犬缨≡海” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵怀薛,是天一觀的道長刺彩。 經(jīng)常有香客問我,道長枝恋,這世上最難降的妖魔是什么迂苛? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮鼓择,結(jié)果婚禮上三幻,老公的妹妹穿的比我還像新娘。我一直安慰自己呐能,他們只是感情好念搬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布抑堡。 她就那樣靜靜地躺著,像睡著了一般朗徊。 火紅的嫁衣襯著肌膚如雪首妖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天爷恳,我揣著相機(jī)與錄音有缆,去河邊找鬼。 笑死温亲,一個(gè)胖子當(dāng)著我的面吹牛棚壁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播栈虚,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼袖外,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了魂务?” 一聲冷哼從身側(cè)響起曼验,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粘姜,沒想到半個(gè)月后鬓照,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孤紧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年颖杏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坛芽。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡留储,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咙轩,到底是詐尸還是另有隱情获讳,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布活喊,位于F島的核電站丐膝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏钾菊。R本人自食惡果不足惜帅矗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望煞烫。 院中可真熱鬧浑此,春花似錦、人聲如沸滞详。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蒲犬,卻和暖如春朱监,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背原叮。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國打工赫编, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奋隶。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓擂送,卻偏偏與公主長得像,于是被迫代替她去往敵國和親达布。 傳聞我的和親對象是個(gè)殘疾皇子团甲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355