鍊錶是一種在物理上非連續,非順序的資料結構,由若干個節點(node)組成。單向鍊錶的每乙個節點包含兩部分,一部分存放資料data,另一部分是指向下乙個節點的指標next。鍊錶的第乙個節點成為頭節點,最後乙個節點稱為尾節點。尾節點的指標指向為空。而雙向列表,就是比單項列表稍微複雜一點,它的每個節點除了有data和next指標外,還有指向前置節點的prev指標。上次我們說到的陣列是在記憶體中順序儲存的,而鍊錶在記憶體中是隨機儲存的。
查詢元素時,鍊錶不能像陣列那樣通過下標快速定位,只能從頭節點逐一查詢。這樣鍊錶的時間複雜度就是o(n)。
不考慮查詢節點的過程,鍊錶的更新也非常容易,像陣列一樣使用新資料替換舊資料即可。
插入節點,鍊錶的插入操作分為3種情況,尾部插入,頭部插入,中間插入。每次只是改動指標的位置便可。具體操作後面**中會比較清晰。
刪除操作,與插入類似,改變指標的指向即可。
class
node
:def
__init__
(self, data)
: self.data = data
self.
next
=none
class
linkedlist
:def
__init__
(self)
: self.size =
0 self.head =
none
self.last =
none
defget
(self, index)
:if index <
0or index >= self.size:
raise exception(
"超出鍊錶節點範圍!"
) p = self.head
for i in
range
(index)
: p = p.
next
return p
definsert
(self, data, index)
:if index <
0or index > self.size:
raise exception(
"超出鍊錶節點範圍!"
) node = node(data)
if self.size ==0:
# 空鍊錶
self.head = node
self.last = node
elif index ==0:
# 插入頭部
node.
next
= self.head
self.head = node
elif self.size == index:
# 插入尾部
self.last.
next
= node
self.last = node
else
:# 插入中間
prev_node = self.get(index-1)
node.
next
= prev_node.
next
prev_node.
next
= node
self.size +=
1def
remove
(self, index)
:if index <
0or index >= self.size:
raise exception(
"超出鍊錶節點範圍!"
)# 暫存被刪除的節點,用於返回
if index ==0:
# 刪除頭節點
removed_node = self.head
self.head = self.head.
next
elif index == self.size -1:
# 刪除尾節點
prev_node = self.get(index-1)
removed_node = prev_node.
next
prev_node.
next
=none
self.last = prev_node
else
:# 刪除中間節點
prev_node = self.get(index-1)
next_node = prev_node.
next
.next
removed_node = prev_node.
next
prev_node.
next
= next_node
self.size -=
1return removed_node
defoutput
(self)
: p = self.head
while p is
notnone
:print
(p.data)
p = p.
next
棧和佇列也是常見的線性資料結構,其實都比較簡單。棧是先進先出,佇列是後進後出。舉個例子,我們在網上衝浪時,不斷地開啟網頁,然後不斷得返回上乙個網頁,最近開啟的也是最先被返回的網頁,這就是典型的棧的結構。最早進入的元素存放的位置叫棧底,最後放入的元素存放的位置叫棧頂。與棧正好相反,佇列是前進先出,就像馬路上的車輛,先到達的也先離開,沒有超車的情況。佇列的出口短叫隊頭,佇列的入口端叫隊尾。
所以佇列的增加刪除都只是對隊頭或者隊尾進行操作。入隊就是在隊尾加入新元素,新元素的下乙個位置就會稱為新的隊尾。出隊就是將隊頭元素移出,原先隊頭的下乙個位置就會稱為新的隊頭。
為了使記憶體能夠得到充分利用。在物理儲存上,隊尾的位置可以在隊頭之前。當再有元素入隊,隊尾指標繼續後移即可。
當(隊尾下標+1)%陣列長度 = 隊頭下標時,代表這個佇列已經滿了。這裡需要注意一下,隊尾指標指向的位置要空出一位,所以佇列最大容量比陣列長度小1。
class
myqueue
:def
__init__
(self, capacity)
: self.
list=[
none
]* capacity
self.front =
0 self.rear =
0def
enqueue
(self, element):if
(self.rear+1)
%len
(self.
list
)== self.front:
raise exception(
"佇列已滿 !"
) self.
list
[self.rear]
= element
self.rear =
(self.rear+1)
%len
(self.
list
)def
dequeue
(self)
:if self.rear == self.front:
raise exception(
"隊列為空 !"
) dequeue_element = self.
list
[self.front]
self.front =
(self.front+1)
%len
(self.
list
)return dequeue_element
defoutput
(self)
: i = self.front
while i != self.rear:
print
(self.
list
[i])
i =(i+1)%
len(self.
list
)
雙端佇列其實是將棧和佇列的特點結合起來,既可以先入先出,也可以先入後出。也就是說隊頭可以入隊出隊,隊尾也可以入隊出隊。細節這裡不再贅述。優先佇列其實是基於二叉堆來實現的,遵循的不是先入先出,而是誰的優先順序最高,誰先出隊。 演算法筆記之棧 佇列 鍊錶
1,佇列 基本概念 佇列是一種特殊的線性結構,它只允許在佇列的首部 head 進行刪除操作 稱為出隊 而在佇列的尾部 tail 進行插入操作 入隊 而當佇列中沒有元素時 即 head tail 稱為空佇列。first in first out fifo 原則 演算法應用 佇列是廣度優先搜尋以及佇列優...
《演算法》筆記 鍊錶 棧和佇列
棧 佇列 表頭插入 第一步 儲存好首節點 第二步 設定新結點 第三步 讓儲存好的首節點指向新結點 node oldfirst first first new node first.item 110 first.next oldfirst 表尾插入 node oldlast last last new...
佇列 棧與鍊錶
佇列,顧名思義,就像排隊一樣,我們只能在隊首刪除,在隊尾增加。佇列是一種先進先出 fifo 的資料結構。參考 佇列的解析與c語言實現 棧,可以理解為乙個儲物的地方,且只有乙個出口,先放進去的東西最後才能拿出來 因為被後面放進去的東西擋住了 棧作為一種 資料結構 是一種 只能在一端進行插入和刪除操作 ...