天天看點

單向連結清單的逆轉(不建立臨時變量)

文章目錄

  • ​​前言​​
  • ​​基本思路​​
  • ​​代碼總覽​​
  • ​​舉例分析​​

前言

在​​單向連結清單的建立與周遊​​中,我們知道了如何建立并且周遊單向連結清單。那麼,如果要将一個連結清單進行逆轉(将連結清單的第一個元素轉為最後一個元素,第二個元素轉為倒數第二個元素,以此類推),又該如何實作呢?

說到這裡,有些博友可能會想到:建立一個臨時變量temp,并建立兩個指針P1,P2,P1指向連結清單開頭,P2指向連結清單末尾,然後通過temp變量将P1和P2指向的結點的資料域進行交換,然後将P1向後移,P2向前移,繼續交換資料域,直到全部交換。這樣必然是可行的,但我們這次的要求是:不建立臨時變量,做到連結清單逆轉。

接下來我們看看如何在不建立臨時變量的情況下将連結清單逆轉。

基本思路

單向連結清單的指針指向是從頭開始,一直指到尾。我們如果想要将一個單向連結清單進行逆轉,隻需在周遊連結清單的時候改變每個結點之間指針的指向即可,即讓單向連結清單的指針指向變成從尾指到頭,最後将逆轉後新連結清單的頭指針傳回即可。

在周遊連結清單的時候,我們是從頭開始周遊,在周遊的過程中需要時刻“記住”下一個結點的位置,否則當我們将某個結點的指針方向改變後就無法找到下一個結點,是以我們可以用一個指針先儲存下一個結點的位址,然後再改變該結點的指針方向,這樣便能找到下一個結點位置了。

代碼總覽

typedef int ElementType;//定義資料類型,可根據需要進行其他類型定義
//連結清單結點定義
typedef struct ListNode
{
  ElementType Data;//資料域,存儲資料
  struct ListNode* Next;//指針域,存儲下一個結點的位址
}Node, *PNode;

PNode ReverseList(PNode List)
{
  PNode Old_head = List;//第一個含有資料的結點位址
  PNode New_head = NULL;
  while (Old_head != NULL)
  {
    PNode Temp = Old_head->Next;//Temp存儲下一個結點的位址
    Old_head->Next = New_head;//改變指針指向
    New_head = Old_head;//New_head後移
    Old_head = Temp;//Old_head讀取下一個結點的位址
  }
  return New_head;//傳回新連結清單的第一個結點位置
}      

舉例分析

僅僅看代碼可能并不能了解代碼的含義,這時我們就得舉個例子,通過畫圖來進一步了解代碼的含義。

例如,某一單向連結清單的資料為:2,3,4,5。我們要對該連結清單進行逆序,代碼執行的過程如下,其中一個長方塊代表一個結點,長方塊左半部分是資料域,右半部分是指針域,紅色線代表目前循環所進行的操作,藍色番号表示執行的先後順序。

循環還未進行時,布局如下:

單向連結清單的逆轉(不建立臨時變量)

當循環進行一次後,布局變為:

單向連結清單的逆轉(不建立臨時變量)

繼續循環:

單向連結清單的逆轉(不建立臨時變量)

再循環:

單向連結清單的逆轉(不建立臨時變量)

再來一次循環:

單向連結清單的逆轉(不建立臨時變量)

這時,因為Old_head為空指針,跳出循環,結果就是這樣的:

單向連結清單的逆轉(不建立臨時變量)

當然,這樣看着不怎麼順眼,我們可以重新排一下位置:

單向連結清單的逆轉(不建立臨時變量)

繼續閱讀