- 鏈表的定義
鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。
- 鏈表類型
- 單鏈表
- 雙鏈表
- 循環鏈表
- 雙向循環鏈表
- 時間複雜度
- 單鏈表
(1)、插入操作只需要改變相鄰節點的指針就可以,例如將a插入n位置只需將n-1位置的next指針指向a,將a的next指針指向n+1。整個操作的時間複雜度爲O(1)
(2)、刪除操作同理只需改變,相鄰節點的指針
(3)、查詢操作最壞時間複雜度爲O(n),與數組的連續存儲空間,只需要首地址和下標就能計算出對應的內存地址不同,鏈表需要根據指針一個節點一個節點地依次遍歷之後才能知道想要查找的數據的相應節點的內存地址。時間複雜度爲O(n)
2、雙鏈表
相對與單鏈表,雙鏈表多了個前驅指針。由此可知雙鏈表比單鏈表佔用更多的內存空間
(1)、插入操作與單鏈表類似,只不過單鏈表插入時。需要遍歷查找到該節點和插入節點的前驅節點。雖然插入和刪除操作O(1)但查找該節點的操作爲O(n),雙鏈表因爲有前驅指針所以不需要重新遍歷就可以找到前驅節點
(2)、刪除操作同理,雖然同爲O(1)的時間複雜度,但是理論上雙鏈表會比單鏈錶快一倍。
3、循環鏈表
與單鏈表類似,只不過循環鏈表從鏈尾到鏈頭比較方便。適合處理一些循環結構的數據。例如’約瑟夫環’
- 雙向循環鏈表
就是雙向鏈表加循環鏈表,如果上面的理解了,這個就比較好理解
- 深入理解
- 指針
在C語言中稱爲指針,python和java中稱爲引用。其功能都是存儲期所指向的對象的內存地址
- 哨兵簡化鏈表實現難度
針對鏈表的插入、刪除操作,需要對插入第一個結點和刪除最後一個節點的情況進行特殊處理。
- python代碼實現
定義鏈表,並實現單鏈表反轉。以後會添加其他相關代碼
class Node(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
class MyLink(object):
def __init__(self,data):
# 尾指針指向最後一個節點,不包括頭結點
self.headnode = Node(None)
self.rear = None
#定義鏈表
for d in data:
NewNode = Node(d)
if self.rear is None:
self.rear = NewNode
self.headnode.next = NewNode
else:
self.rear.next = NewNode
self.rear = NewNode
#打印鏈表
def print_all(self):
next = self.headnode.next
while next is not None:
print(next.data,end=' ')
next = next.next
print()
# 頭插法實現反轉
def reverse(self):
# 將鏈表的頭結點之後的元素分開來
next = self.headnode.next
self.headnode.next = None
while next is not None:
NewNode = next
next = next.next
NewNode.next = self.headnode.next
self.headnode.next = NewNode
# 遞歸實現
def reverse2(self):
next = self.headnode.next
self.print_next(next)
print()
def print_next(self,next):
if next is None:
return
self.print_next(next.next)
print(next.data,end=' ')
def get_last_k_node(self,k):
advance_node = self.headnode.next
behind_node = self.headnode.next
while k>0:
if advance_node is None:
return None
advance_node = advance_node.next
k -= 1
while advance_node is not None:
advance_node = advance_node.next
behind_node = behind_node.next
return behind_node.data
def main():
data = [1,2,3,4,5]
queue = MyLink(data)
queue.print_all()
print(queue.get_last_k_node(1))
queue.reverse2()
queue.reverse()
queue.print_all()
if __name__ == '__main__':
main()
鏈表中環檢測
class Node():
def __init__(self,data,next=None):
self.data = data
self.next = next
class MyLink(object):
def __init__(self,data):
self.headnode = Node(None)
self.rear = None
for d in data:
NewNode = Node(d)
if self.rear is None:
self.rear = NewNode
self.headnode.next = NewNode
else:
self.rear.next = NewNode
self.rear = NewNode
#self.rear.next = self.headnode
def cry(self):
slow , fast = self.headnode ,self.headnode
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
if __name__ == "__main__":
data = [1,2,3,4,56,7]
ml = MyLink(data)
print(ml.cry())