雙向鏈表
一種更加複雜的鏈表,特徵是每個節點有兩個鏈接:一個指向前一個節點,一個指向後一個節點,處理時只需要管前一個節點的後(next),後一個結節點的前(prev)即可。
特殊情況,當節點爲第一個節點時prev指向空值(None),當節點爲最後一個節點時next指向空值(None)
1.頭部插入更改的代碼以及原理:
node.next = self.__head
self.__head = node
node.next.prev = node
2.指定位置插入
指定位置插入有兩種方法:
3.刪除
這裏非常體現操作前一個節點的next,後一個節點的prev。
4.尾部插入(略)
測試代碼
class Node(object):
"""節點"""
def __init__(self, item):
self.elem = item
self.next = None
self.prev = None # 多定義一個前驅
class DoubleLinkList(object):
"""雙鏈表"""
def __init__(self, node=None): # 3: 如果用戶不輸入頭節點值 當成默認參數 None 直接創建空列表 None 其實又回到了下面一行
# self.__head = None 1:一上來設置爲空 意思是不指向任何節點 | 私有加 __ 意義:只有這個函數內部使用
self.__head = node # 2:在上一行的基礎上人性化,用戶如果先構造節點,就將頭指向這個頭節點 node
def is_empty(self):
"""鏈表是否爲空"""
return self.__head is None # class在變量和None進行比較時,應該使用 is。
# 可以把比較的值直接作爲返回值 如果相等即爲真就是1 即返回1
# 只要頭節點指的是空那麼就是空鏈表
def length(self):
"""鏈表長度"""
cur = self.__head # 讓它等於指向表頭指向的第一個節點,cur 用於移動遍歷元素
# count 記錄數量
count = 0
while cur is not None: # count 從0開始的好處就是能夠記錄空表的長度,一個代碼實現空表與一般表的長度計算
count += 1
cur = cur.next # cur指向了 下一個節點
return count
def travel(self):
"""遍歷整個鏈表"""
cur = self.__head
while cur is not None:
print(cur.elem, end=" ") # 打印每一個元素 空格隔開
cur = cur.next
print("") # 換行
def add(self, item):
"""鏈表頭部添加元素,頭插法"""
node = Node(item) # 把item這個數據封裝成鏈表所需要的節點形式
node.next = self.__head
self.__head = node # 當一開始是空的時候 頭和節點都指向None 所以跑一遍上述兩行還是滿足的
node.next.prev = node # node 節點的n指向的p指向node本身
def append(self, item):
"""鏈表尾部添加元素,尾插法"""
node = Node(item)
if self.is_empty(): # 如果鏈表是空的 頭直接指向插入的節點
self.__head = node
else:
cur = self.__head
while cur.next is not None:
cur = cur.next
cur.next = node
node.prev = cur
def insert(self, pos, item):
"""指定位置添加元素
:param item: 元素
:param pos從0開始
"""
if pos <= 0: # 如果輸入位置是<=0的默認是在頭部插入
ll.add(item)
elif pos > self.length() - 1:
self.append(item)
else:
cur = self.__head
count = 0
while count < pos: # 不需要兩個遊標只需要一個了
count += 1
cur = cur.next
# 當循環退出後 cur指向pos位置
node = Node(item)
node.next = cur # 這四句話是完成指定位置插入的操作過程
node.prev = cur.prev
cur.prev.next = node
cur.prev = node
def remove(self, item):
"""刪除節點,找到和你想刪除的數一樣的數"""
cur = self.__head
while cur is not None:
if cur.elem == item:
# 先判斷此節點是否是頭節點 如果是頭節點
if cur == self.__head:
self.__head = cur.next
if cur.next: # 判斷鏈表是否只有一個元素
cur.next.prev = None
else:
cur.prev.next = cur.next
if cur.next:
cur.next.prev = cur.prev
break
else: # 移動
cur = cur.next
def search(self, item):
"""鏈表查找節點是否存在,並返回True或者False"""
cur = self.__head
while cur is not None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
# 測試代碼
if __name__ == "__main__":
ll = DoubleLinkList()
print(ll.is_empty())
print(ll.length())
ll.append(1)
print(ll.is_empty())
print(ll.length())
ll.append(2)
ll.add(8)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
ll.insert(-1, 9)
ll.travel()
ll.insert(2, 100)
ll.travel()
ll.insert(10, 200)
ll.travel()
ll.remove(200)
ll.travel()
ll.insert(20, 200)
ll.travel()
ll.insert(21, 200)
ll.travel()
ll.remove(200)
ll.travel()