雙向鏈表
雙向鏈表有兩個指針域,一個指向前驅結點,一個指向後繼結點
創建一個結點類:
因爲是雙向鏈表,所以需要前後相通,就是比單鏈表多了一個前驅指針
數據域data、前驅指針pre,後繼指針next
class Node(object):
"""創建一個結點類"""
def __init__(self, data):
self.data = data
self.pre = None
self.next = None
創建一個創建雙向鏈表的類:
判斷是否爲空、獲取長度、遍歷鏈表、查找指定結點是否存在,這些函數和單鏈表的一樣
(只是最簡單的方法一樣,雙向鏈表還有其它方法遍歷或者查找指定結點)
class CreateDoubleLinkedList(object):
"""創建一個創建雙向鏈表的類"""
def __init__(self):
self.head = None
def is_empty(self):
"""判斷雙向鏈表是否爲空鏈表"""
return self.head is None
def length(self):
"""獲取雙向鏈表的長度"""
cur = self.head
count = 0
while cur is not None:
count += 1
cur = cur.next
return count
def traversal(self):
"""遍歷雙向鏈表"""
cur = self.head
if self.is_empty():
print("鏈表爲空!")
return
while cur is not None:
print(cur.data)
cur = cur.next
def node_is_exist(self, data):
"""查找指定結點是否存在"""
cur = self.head
while cur is not None:
if cur.data == data:
return True
else:
cur = cur.next
return False
在頭部添加結點:
插入的大體過程和單鏈表很相似,只是在插入結點的過程中,我們需要注意的就是:每個結點都有兩個指針,都需要設置正確的指向。
def add_first(self, data):
"""在頭部添加結點"""
node = Node(data)
if self.is_empty():
self.head = node
else:
# 新結點向後指向頭結點
node.next = self.head
# 頭結點向前指向新結點
self.head.pre = node
# 將頭結點的稱號給新結點
self.head = node
在尾部添加結點:
def add_last(self, data):
"""在尾部添加結點"""
node = Node(data)
if self.is_empty():
self.head = node
else:
cur = self.head
# 指針移動到尾部
while cur.next is not None:
cur = cur.next
# 尾結點的後繼指針指向新結點
cur.next = node
# 新結點的前驅指針指向尾結點
node.pre = cur
在指定位置添加結點:
def insert_node(self, index, data):
"""在指定位置添加結點"""
if index < 0 or index > self.length():
print("結點位置錯誤!")
return False
elif index == 0:
self.add_first(data)
elif index == self.length():
self.add_last(data)
else:
node = Node(data)
cur = self.head
pres = None
count = 0
# 移動到要添加的位置
while count < index:
pres = cur
cur = cur.next
count += 1
# 新結點和它前面的結點互指
pres.next = node
node.pre = pres
# 新結點和它後面的結點互指
node.next = cur
cur.pre = node
刪除指定結點:
當鏈表不爲空的時候,我們需要考慮三種情況:
- 要刪除是是頭結點
- 要刪除的是尾結點
- 要刪除的是中間任意結點
(需要注意的就是:每個結點都需要改變兩個指針鏈)
def remove_node(self, data):
"""刪除指定結點"""
if self.is_empty():
print("刪除失敗,鏈表爲空!")
return False
elif data == self.head.data:
self.head.next.pre = None
self.head = self.head.next
else:
cur = self.head
# 移動到要刪除結點的位置
while cur.data != data:
cur = cur.next
# 當前結點的後繼結點爲空,說明是尾結點
if cur.next is None:
cur.pre.next = None
cur.pre = None
else:
cur.pre.next = cur.next
cur.next.pre = cur.pre
假如我們只斷掉了一根指針鏈,會怎麼樣?
就比如這樣寫(以上面刪除尾結點的代碼爲例):
# 當前結點的後繼結點爲空,說明是尾結點
if cur.next is None:
cur.pre.next = None
# 將尾結點指向前驅結點的那個指針鏈留着
# cur.pre = None
# 打印一下被刪掉的尾結點的前驅結點數據
print("測試:", cur.pre.data)
如果尾結點已經被刪掉了,那麼cur指向爲空,最後print那一行,空類型是沒有前驅結點pre屬性的,測試運行之後,肯定會報錯。
但是因爲我們只刪掉了一個指針鏈,所以測試結果還是會打印出:被刪除掉結點的前驅結點數據,因爲被刪除結點的前驅指針鏈沒有被斷掉。
接下來我們正向遍歷一次鏈表,發現:沒有被剛纔刪除的結點數據,爲什麼?因爲向右的指針鏈已經被斷掉了,遍歷不到它,我們以爲被它被刪除掉了,其實沒有。
所以:雙向鏈表必須要端兩根指針鏈,才能徹底刪除掉。
(可以自行寫一個反向遍歷的函數,看一看效果)
主函數測試:
if __name__ == '__main__':
lists = CreateDoubleLinkedList()
lists.add_last(3)
lists.add_first(2)
lists.add_first(1)
lists.add_last(5)
lists.insert_node(3, 4)
lists.traversal()
print("鏈表是否爲空:", lists.is_empty())
print("獲取鏈表長度:", lists.length())
print("改結點是否存在:", lists.node_is_exist(2))
lists.remove_node(1)
lists.remove_node(5)
print("刪除結點之後的遍歷:")
lists.traversal()
測試結果截圖:
完整代碼:
class Node(object):
"""創建一個結點類"""
def __init__(self, data):
self.data = data
self.pre = None
self.next = None
class CreateDoubleLinkedList(object):
"""創建一個創建雙向鏈表的類"""
def __init__(self):
self.head = None
def is_empty(self):
"""判斷雙向鏈表是否爲空鏈表"""
return self.head is None
def length(self):
"""獲取雙向鏈表的長度"""
cur = self.head
count = 0
while cur is not None:
count += 1
cur = cur.next
return count
def traversal(self):
"""遍歷雙向鏈表"""
cur = self.head
if self.is_empty():
print("鏈表爲空!")
return
while cur is not None:
print(cur.data)
cur = cur.next
def node_is_exist(self, data):
"""查找指定結點是否存在"""
cur = self.head
while cur is not None:
if cur.data == data:
return True
else:
cur = cur.next
return False
def add_first(self, data):
"""在頭部添加結點"""
node = Node(data)
if self.is_empty():
self.head = node
else:
# 新結點向後指向頭結點
node.next = self.head
# 頭結點向前指向新結點
self.head.pre = node
# 將頭結點的稱號給新結點
self.head = node
def add_last(self, data):
"""在尾部添加結點"""
node = Node(data)
if self.is_empty():
self.head = node
else:
cur = self.head
# 指針移動到尾部
while cur.next is not None:
cur = cur.next
# 尾結點的後繼指針指向新結點
cur.next = node
# 新結點的前驅指針指向尾結點
node.pre = cur
def insert_node(self, index, data):
"""在指定位置添加結點"""
if index < 0 or index > self.length():
print("結點位置錯誤!")
return False
elif index == 0:
self.add_first(data)
elif index == self.length():
self.add_last(data)
else:
node = Node(data)
cur = self.head
pres = None
count = 0
# 移動到要添加的位置
while count < index:
pres = cur
cur = cur.next
count += 1
# 新結點和它前面的結點互指
pres.next = node
node.pre = pres
# 新結點和它後面的結點互指
node.next = cur
cur.pre = node
def remove_node(self, data):
"""刪除指定結點"""
if self.is_empty():
print("刪除失敗,鏈表爲空!")
return False
elif data == self.head.data:
self.head.next.pre = None
self.head = self.head.next
else:
cur = self.head
# 移動到要刪除結點的位置
while cur.data != data:
cur = cur.next
# 當前結點的後繼結點爲空,說明是尾結點
if cur.next is None:
cur.pre.next = None
cur.pre = None
else:
cur.pre.next = cur.next
cur.next.pre = cur.pre
if __name__ == '__main__':
lists = CreateDoubleLinkedList()
lists.add_last(3)
lists.add_first(2)
lists.add_first(1)
lists.add_last(5)
lists.insert_node(3, 4)
lists.traversal()
print("鏈表是否爲空:", lists.is_empty())
print("獲取鏈表長度:", lists.length())
print("改結點是否存在:", lists.node_is_exist(2))
lists.remove_node(1)
lists.remove_node(5)
print("刪除結點之後的遍歷:")
lists.traversal()