集合系列 LinkedList原始碼分析

2021-08-19 03:39:06 字數 3570 閱讀 5004

本篇介紹的linkedlist是list介面的另一種實現,它的底層是基於雙向鍊錶實現的,因此它具有插入刪除快而查詢修改慢的特點,此外,通過對雙向鍊錶的操作還可以實現佇列和棧的功能。

linkedlist的底層結構如下圖所示。

f表示頭結點引用,l表示尾結點引用,鍊錶的每個結點都有三個元素,分別是前繼結點引用(p),結點元素的值(e),後繼結點的引用(n)。結點由內部類node表示,我們看看它的內部結構。

//結點內部類

private

static

class

node

}

node這個內部類其實很簡單,只有三個成員變數和乙個構造器,item表示結點的值,next為下乙個結點的引用,prev為上乙個結點的引用,通過構造器傳入這三個值。接下來再看看linkedlist的成員變數和構造器。

//集合元素個數

transient

int size = 0;

//頭結點引用

transient nodefirst;

//尾節點引用

transient nodelast;

//無參構造器

public

linkedlist

(){}

//傳入外部集合的構造器

public

linkedlist

(collection extends e> c)

linkedlist持有頭結點的引用和尾結點的引用,它有兩個構造器,乙個是無參構造器,乙個是傳入外部集合的構造器。與arraylist不同的是linkedlist沒有指定初始大小的構造器。看看它的增刪改查方法。

//增(新增)

public

boolean

add(e e)

//增(插入)

public

void

add(int index, e element)

else 

}//刪(給定下標)

public e remove

(int index)

//刪(給定元素)

public

boolean

remove

(object o)

}} else }}

return

false;

}//改

public e set

(int index, e element)

//查public e get

(int index)

linkedlist的新增元素的方法主要是呼叫linklast和linkbefore兩個方法,linklast方法是在鍊錶後面鏈結乙個元素,linkbefore方法是在鍊錶中間插入乙個元素。linkedlist的刪除方法通過呼叫unlink方法將某個元素從鍊錶中移除。下面我們看看鍊錶的插入和刪除操作的核心**。

//鏈結到指定結點之前

void

linkbefore

(e e, nodesucc)

else 

//集合元素個數加一

size++;

//修改次數加一

modcount++;

}//解除安裝指定結點

e unlink

(nodex)

else 

//如果給定結點的下乙個結點為空, 說明給定結點為尾結點

if (next == null)  else 

//將給定結點的元素置空

x.item = null;

//集合元素個數減一

size--;

//修改次數加一

modcount++;

return element;

}

linkbefore和unlink是具有代表性的鏈結結點和解除安裝結點的操作,其他的鏈結和解除安裝兩端結點的方法與此類似,所以我們重點介紹linkbefore和unlink方法。

linkbefore方法的過程圖:

unlink方法的過程圖:

通過上面圖示看到對鍊錶的插入和刪除操作的時間複雜度都是o(1),而對鍊錶的查詢和修改操作都需要遍歷鍊錶進行元素的定位,這兩個操作都是呼叫的node(int index)方法定位元素,看看它是怎樣通過下標來定位元素的。

//根據指定位置獲取結點

nodenode(int index) 

return x;

} else 

return x;

}}

通過下標定位時先判斷是在鍊錶的上半部分還是下半部分,如果是在上半部分就從頭開始找起,如果是下半部分就從尾開始找起,因此通過下標的查詢和修改操作的時間複雜度是o(n/2)。通過對雙向鍊錶的操作還可以實現單項佇列,雙向佇列和棧的功能。

單向佇列操作:

//獲取頭結點

public e peek

()//獲取頭結點

public e element

()//彈出頭結點

public e poll

()//移除頭結點

public e remove

()//在佇列尾部新增結點

public

boolean

offer

(e e)

雙向佇列操作:

//在頭部新增

public

boolean

offerfirst

(e e)

//在尾部新增

public

boolean

offerlast

(e e)

//獲取頭結點

public e peekfirst

()//獲取尾結點

public e peeklast

()

棧操作:

//入棧

public

void

push

(e e)

//出棧

public e pop

()

不管是單向佇列還是雙向佇列還是棧,其實都是對鍊錶的頭結點和尾結點進行操作,它們的實現都是基於addfirst(),addlast(),removefirst(),removelast()這四個方法,它們的操作和linkbefore()和unlink()類似,只不過乙個是對鍊錶兩端操作,乙個是對鍊錶中間操作。可以說這四個方法都是linkbefore()和unlink()方法的特殊情況,因此不難理解它們的內部實現,在此不多做介紹。到這裡,我們對linkedlist的分析也即將結束,對全文中的重點做個總結:

LinkedList集合整理

jdk1.6以後的新特性 addfirst offerfirst addlast offerlast getfirst peekfirst getlast peeklast removefirst pollfirst removelast polllast jdk1.6以後,刪除或獲取元素時,如果列...

泛型集合 LinkedList

using system using system.collections.generic using system.linq using system.text using system.collections namespace linkedlist class program static v...

集合 list 迭代 linkedList

集合類 定義 用於儲存物件最常用的一種方式 集合類與陣列的比較 陣列和集合類同是容器,陣列雖然也可以儲存物件,但是長度固定,而集合類為可變長度,陣列可儲存基本資料型別,集合只存放物件,而且可以存放不同型別的物件。集合框架中的常用介面 collection 介面有兩個子介面 list 列表 set 集...