1. 程式人生 > >100行程式碼手寫模擬一個LinkedList

100行程式碼手寫模擬一個LinkedList

前言:

    首先先說一下昨天的模擬ArrayList中的remove()方法,昨晚思考了一下,那麼實現不太好,所以又想了一個新的演算法,具體如下,假如現在需要remove的index是2,那麼就從index+1位置到陣列最後的size開始迴圈,依次把下一個值賦給上一個,比如說4賦值給3的位置,5到4的位置依次進行,這樣3就被移除了。程式碼如下:

 

一、LinkedList、ArrayList

    

         查詢       新增        刪除    實現原理
ArrayList     效率高    效率低      效率低       陣列
LinkedList     效率低    效率高     效率高       連結串列

 

二、LinkedList的實現

    在JDK中LinkedList的實現是基於雙向迴圈列表,學過資料結構我們就知道連結串列的特點,在進行查詢的時候它不能向陣列一樣,直接根據下標index來取值,而是需要從第一個節點到index節點遍歷,因此查詢效率是極其低下的。

    進行插入的時候,ArrayList如果不需要擴容那效率沒什麼問題,但是如果要擴容的話,那首先會建立一個新的陣列,然後把原來的資料複製到新陣列中去,這樣資料量大的話,效率是很低下的。而LinkedList是基於雙向連結串列的實現,我們知道雙向連結串列的頭節點(Header)是直接可以指到最後的節點的,這樣在新增的時候,只需要在最後一個節點後面再加一個節點(新值)就可以了,所以LinkedList的新增效率極快。

    ArrayList迴圈刪除元素的時候,從後往前遍歷來進行刪除(效率比從前往後要高),對比前言裡面的圖大家體會下,總體來說ArrayList的刪除元素很慢。

    LinkedList刪除元素的時候,從前和從後的效率都很快,因為Header可以指向最後同時也是最前的節點,反而是刪除中間比較慢,但即使是這樣,綜合來說LinkedList的效率也要比ArrayList高的多。因為LinkedList最壞的結果也就是迴圈到中間,而ArrayList最壞是要迴圈除第一個節點外的其他節點。

 

三、使用單向連結串列模擬LinkedList

    使用單向連結串列來模擬LinkedList時,我們的準備工作當然是要建立一個節點Node物件。需要設定一個Object型別的value值,另一個是指向下一個節點的指標,但是Java中沒有指標這個概念,怎麼辦呢?我們採用引用來解決,定義一個Node型別的引用用來指向下一個節點。程式碼如下:截圖省略了setter、getter方法。

 

        

    接下來的工作就是使用連結串列實現了,在連結串列中由於我們使用的是單向的連結串列,因此只需要定義size(長度)和Node head(頭節點),接下來我們來看下add方法

    

 

    解釋一下:在新增的時候,首先判斷新增的節點是不是頭節點,如果是說明是第一個節點,就直接把node設定為head。如果不是第一個節點,那麼我們就把它設定到接下來的節點,需要注意的是temp保留的是頭節點的值,相當於從頭節點開始尋找不為空的節點,然後設定進去。如果temp的下一個節點是空節點那麼表示是最後一個節點,因為在單向連結串列中最後節點沒有下一個節點了,這時就直接把node設定進去。

    接下來是set() 方法,分析一下,在設定值的時候從0開始到index位置進行迴圈,迴圈後便找到了index,接著把value直接賦給這個節點。

    

 

 

而get() 的時候和set原理基本一致,只是將找到的值返給使用者。

    

 

 

clear()就不多做解釋了直接將Head賦值為空,size為0就可以

 

重點看下remove

 解釋:如果要移除的是第一個節點,那麼將第一個節點指向下一個節點,也就相當於head這個引用指向下一個節點,不指向第一個節點,也就代表第一個節點不存在了,因為沒引用了。

  如果刪除的不是第一個節點,那麼就從head開始遍歷到index-1,也就是要刪除元素的上一個元素,然後將index-1位置的節點和index+1位置的節點連線起來,之後size--就好。還是畫個圖解釋下如果現在要刪除是3這個節點。所以你需要把2的位置和4連線起來對吧,因此就是2位置的下一個的下一個。

 

四、測試

    

 

 

 

五、總結

    有時候從實現上去比較他們之前的原理會更便於理解。

 

更多內容請關注公眾號: