1. 程式人生 > >資料結構-連結串列結構分析(LinkedList)。

資料結構-連結串列結構分析(LinkedList)。

轉載請註明作者:Edison丶夢楠

如有錯誤之處,還請您務必在留言區留下您的寶貴經驗。或傳送郵箱:[email protected] 告知。

本人非常感謝!希望能和您共同學習,共同進步!

下面介紹連結串列的兩種結構:

單向連結串列:只能從頭遍歷到尾,或者從尾遍歷到頭。

圖例:

next:獲取下一個節點。

ele:每個節點中的元素。

first:指頭部,連結串列中第一個元素。

我們可以理解為,當拿到連結串列物件,呼叫first()就可以得到第一個元素。

size:指元素的個數。(或連結串列的長度-1,索引從0開始),在集合中沒有length一說。陣列中的length相當於集合框架中的size

模擬程式碼為:

//單向連結串列 

class Node{
  Node next: //下一個節點 宣告方法
  Object ele: //節點中的資料 宣告方法

  public static void main(String [] Nodetest){
    Node cnode = new Node();
    cnode.next(); //獲取下一個元素
    cnode.ele();  //獲取當前節點元素。
    cnode.next().ele(); //獲取下一個節點中的元素
}

}

雙向連結串列:可以從頭遍歷到尾,也可以從尾遍歷到頭。

我們可以理解為,雙向連結串列其實就是兩個單向連結串列的合成。只不過是一個從頭到尾,一個從尾到頭。

圖例:

prev:表示上一個節點

Node first:拿到第一個節點

Node last:拿到最後一個節點。

模擬程式碼:

//模擬雙向連結串列程式碼

class Node{
  Node first: //第一個節點  宣告方法
  Node last:  //最後一個節點  宣告方法
  Node prev:  //上一個節點
  Node next: //下一個節點 宣告方法
  Object ele: //節點中的資料 宣告方法

  public static void main(String [] Nodetest){
    Node cnode = new Node();
    cnode.next(); //獲取下一個節點
    cnode.ele();  //獲取當前節點元素。
    cnode.next().ele(); //獲取下一個節點中的元素

    cnode.first();  //獲取第一個節點
    cnode.last();   //獲取最後一個節點
    cnode.prev();    //獲取上一個節點
    

}

}

基於連結串列的實現程式碼:

//基於雙向連結串列的集合
  /**
    *具體操作程式碼請參見LinkedList原始碼
    *這裡不作具體實現
    */
pub11c class MyLinkedL1st {

      private Node first;//連結串列的第一個節點
      private Hode last;//連結串列的最後一個節點
      private int s1ze;//節點的數量
        //連結串列中的每一個節點
     class Node {

      Node prev;//上一個節點物件

      Node  Next;//下一個節點物件

      Object ele;//當前節點中儲存的元素
   
    }
}

總結:對於連結串列操作,無疑是雙向連結串列功能更強大。而雙向連結串列在取頭和尾的時候速度更快。

對於連結串列LinkedList的具體實現,我們仔細讀原始碼可以得出:

刪除操作上,連結串列結構相對於陣列結構要更快。

為什麼呢?

陣列每次進行刪除操作都要進行移位與遍歷。當某個元素被刪除時,後面的元素要向前補位。最後一個元素設為null,

然後再刪除最後一個元素所佔的記憶體空間。  

連結串列的刪除操作演算法分析:

刪除(first也可當做current)即第一個節點時,把下一個節點的next賦給第一個節點的next。把第一個節點的prev設為null;

刪除最後一個節點時,把最後一個節點的prev賦給當前物件的last,再把current節點的上一個(prev)節點的next設為null;

刪除中間(此處中間節點指將要被刪除的節點current)節點時,把current節點的next賦給current節點的上一個節點的next。

再把current節點的prev賦給current節點的下一個節點的prev。

下面給出具體實現程式碼:

前文說過,LinkedList在向頭和尾新增元素時,效能更優。下面給出具體實現程式碼及程式碼分析:

在向頭部新增元素時演算法實現:

把新增之前第一個節點設為新增節點的next節點,然後把新增節點作為之前第一個節點的上一個節點。(或換種說法:把之前第一個節點的上一個節點作為新增節點),再把新增節點作為第一個節點。而新增節點的prev最好設定為null

向尾部新增元素演算法實現:

把新增節點作為之前最後一個節點的next節點,再把之前最後一個節點作為新增節點的上一個節點。

再把物件的last屬性設定為新增節點即可。

      對LinekdList操作的效能分析:

     1):增操作:

      雙向連結串列可以直接獲取自己的第一個和最後一一個節點,

      如果新增的元素在第一個或最後一 個位置,那麼操作只有1次.

      2):刪除操作(removeFisrt,removelast):

      如果刪除第一個元素:操作一一次.如果操作最後一個元素:操作一次如果刪除中間的元素:

      找到元素節點平均操作:(1+N)/2次.找到節點之後做刪除操作: 1次.3):查詢操作:

      平均:(N+1y2次4):修改操作:

      平均:(N+1)/2次  

基於前文(ArrayList效能分析),我們可以得出ArrayList和LinkedList的各自優異之處。基於陣列的列表和基於連結串列的列表的效能對比:                                                                     Arraylist:查詢,更改較快,新增和刪除較慢                                                                     Linkeduist查詢更改較慢,新增和刪除較快