單鏈表反轉-C語言實現

1、理解指針

        看懂鏈表的結構並非很難,可是一旦把它和指針混在一塊兒,就很容易讓人摸不着頭腦。因此,要想寫對鏈表代碼,首先就要理解好指針。程序員

  有些語言有「指針」的概念,好比 C 語言;有些語言沒有指針,取而代之的是「引用」,好比 Java、Python。不論是「指針」仍是「引用」,實際上,它們的意思都是同樣的,都是存儲所指對象的內存地址。編程

  將某個變量賦值給指針,實際上就是將這個變量的地址賦值給指針,或者反過來講,指針中存儲了這個變量的內存地址,指向了這個變量,經過指針就能找到這個變量。數組

  p->next=q。這行代碼是說,p 結點中的 next 指針存儲了 q 結點的內存地址。p->next=p->next->next。這行代碼表示,p 結點的 next 指針存儲了 p 結點的下下一個結點的內存地址。編程語言

        C語言標準規定,對於一個符號的定義,編譯器老是從它的名字開始讀取,而後按照優先級順序依次解析。對,從名字開始,不是從開頭也不是從末尾,這是理解複雜指針的關鍵!

   對於初學者,有幾種運算符的優先級很是容易混淆,它們的優先級從高到低依次是:函數

    • 定義中被括號( )括起來的那部分。
    • 後綴操做符:括號( )表示這是一個函數,方括號[ ]表示這是一個數組。
    • 前綴操做符:星號*表示「指向xxx的指針」。

    在本章中咱們最多隻用到二級指針所以將對二級指針作下說明。好比int **p,是什麼意思?spa

      首先看 *p 。 「*」表示P是一個指針。可是是指向什麼的指針呢?指針

      在看前面的int* ,int是一個整型類型後面加一個「*」表示整型類型的指針。code

  *p就是指向整型類型指針的指針。p保存的是整型類型指針的地址。對象

2、警戒指針丟失和內存泄漏

  不知道你有沒有這樣的感受,寫鏈表代碼的時候,指針指來指去,一下子就不知道指到哪裏了。因此,咱們在寫的時候,必定注意不要弄丟了指針。指針每每都是怎麼弄丟的呢?我拿單鏈表的插入操做爲例來給你分析一下。blog

  指針每每都是怎麼弄丟的呢?我拿單鏈表的插入操做爲例來給你分析一下。

  如圖所示,咱們但願在結點 a 和相鄰的結點 b 之間插入結點 x,假設當前指針 p 指向結點 a。若是咱們將代碼實現變成下面這個樣子,就會發生指針丟失和內存泄露。

1 p->next = x;  // 將p的next指針指向x結點;
2 x->next = p->next;  // 將x的結點的next指針指向b結點;

  初學者常常會在這兒犯錯。p->next 指針在完成第一步操做以後,已經再也不指向結點 b 了,而是指向結點 x。第 2 行代碼至關於將 x 賦值給 x->next,本身指向本身。所以,整個鏈表也就斷成了兩半,從結點 b 日後的全部結點都沒法訪問到了。

  對於有些語言來講,好比 C 語言,內存管理是由程序員負責的,若是沒有手動釋放結點對應的內存空間,就會產生內存泄露。因此,咱們插入結點時,必定要注意操做的順序,要先將結點 x 的 next 指針指向結點 b,再把結點 a 的 next 指針指向結點 x,這樣纔不會丟失指針,致使內存泄漏。因此,對於剛剛的插入代碼,咱們只須要把第 1 行和第 2 行代碼的順序顛倒一下就能夠了。同理,刪除鏈表結點時,也必定要記得手動釋放內存空間,不然,也會出現內存泄漏的問題。固然,對於像 Java 這種虛擬機自動管理內存的編程語言來講,就不須要考慮這麼多了。

3、單鏈表反轉的C語言實現

   

  使用p指向第一個結點,cur指向當前結點,每次把cur->next結點摘掉放在p節點前面。而後更新p結點指向頭結點。具體實現代碼以下所示

 47 void revers_list(list1 **l)
 48 {
 49     if(!(*l)||!l)
 50     {
 51         exit(-1);
 52     }
 53 
 54     list1 *start=*l;
 55     list1 *start_next=NULL;
 56 
 57     while (start->next)
 58     {
 59         // 獲取當前節點的後繼節點 
 60          start_next = start->next; 
 61         // 將後繼節點摘鏈 72     
 62          start->next = start_next->next; 
 63         // 將後繼節點提到最前面 
 64         start_next->next = *l; 
 65         // 更新頭節點 
 66         *l = start_next;
 67     }
 68 }


相關文章
相關標籤/搜索