python 釋放連結串列節點_四種常見連結串列的實現及時間複雜度分析(Python3版)
阿新 • • 發佈:2021-01-13
技術標籤:python 釋放連結串列節點
四種常見的連結串列包括:單向連結串列,單向迴圈連結串列,雙向連結串列,雙向迴圈連結串列。
要實現的連結串列操作包括
- is_empty()
判斷連結串列是否為空
- length()
求連結串列長度
- traversing()
遍歷所有節點元素
- add()
頭部新增節點
- append()
尾部新增節點
- insert(pos, item)
某個位置插入節點
- remove(item)
刪除一個節點
- search(item)
查詢某個節點是否存在
先初始化節點
class Node(object): """單節點""" def __init__(self, elem): self.elem = elem self.next = None class DoubleNode(Node): """雙節點""" def __init__(self, elem): super(DoubleNode, self).__init__(elem) self.prev = None
四種連結串列的實現中,每一個類都繼承自object
, self.__head
是私有變數,不能被子類或外部呼叫。 ```python [s-單向連結串列] class SingleLinkList(object): """單向連結串列"""
def __init__(self, node=None): self.head = node def is_empty(self) -> bool: """連結串列是否為空 O(1)""" return self.head is None def length(self) -> int: """連結串列長度 O(n)""" count, cur = 0, self.head while cur is not None: cur = cur.next # 不要寫錯cur = self.head.next, self.__next不是活動指標 count += 1 return count def traversing(self) -> '': """遍歷所有節點 O(n)""" cur = self.head # 不是 self._head while cur is not None: print(cur.elem, end=' ') cur = cur.next return '' def add(self, item) -> None: """頭部新增節點 O(1)""" node = Node(item) node.next = self.head self.head = node def append(self, item) -> None: """尾部新增節點 O(n)""" node = Node(item) cur = self.head if self.is_empty(): self.head = node else: while cur.next is not None: cur = cur.next cur.next = node def insert(self, position: int, item) -> None: """ 節點插入到某個位置 O(n) :param position: 0表示第1個位置 :param item: :return: None """ if position <= 0: self.add(item) elif position >= self.length(): self.append(item) else: node = Node(item) count, cur = 1, self.head while count < position: cur = cur.next count += 1 node.next = cur.next cur.next = node def remove(self, item) -> None: """刪除連結串列中的一個節點 O(n)""" pre, cur = None, self.head while cur is not None: if cur.elem == item: if cur == self.head: self.head = cur.next break # 只remove第一個元素 pre.next = cur.next break pre = cur cur = cur.next def search(self, item) -> bool: """查詢節點是否存在 O(n)""" cur = self.head while cur is not None: if cur.elem == item: return True cur = cur.next return False ```python [s-單向迴圈連結串列] class SingleCycleLinkList(object): """單向迴圈連結串列""" def __init__(self, node=None): self.__head = node if node: node.next = node def is_empty(self) -> bool: """連結串列是否為空 O(1)""" return self.__head is None def length(self) -> int: """連結串列長度 O(n)""" if self.is_empty(): return 0 count, cur = 1, self.__head while cur.next != self.__head: cur = cur.next # 不要寫錯cur = self.__head.next, self.__next不是活動指標 count += 1 return count def transverse(self) -> '': """遍歷所有節點 O(n)""" if not self.is_empty(): cur = self.__head # 不是 self._head while cur.next != self.__head: print(cur.elem, end=' ') cur = cur.next print(cur.elem, end=' ') return '' def add(self, item) -> None: """頭部新增節點 O(n)""" node = Node(item) if self.is_empty(): self.__head = node node.next = node else: cur = self.__head while cur.next != self.__head: cur = cur.next # 退出while迴圈之後cur指向尾結點 node.next = self.__head self.__head = node cur.next = self.__head def append(self, item) -> None: """尾部新增節點 O(n)""" node = Node(item) if self.is_empty(): self.__head = node node.next = node else: cur = self.__head while cur.next != self.__head: cur = cur.next cur.next = node node.next = self.__head def insert(self, position: int, item) -> None: """ 節點插入到某個位置 O(n) :param position: 0表示第1個位置 :param item: :return: None """ if position <= 0: self.add(item) elif position >= self.length(): self.append(item) else: node = Node(item) count, cur = 1, self.__head while count < position: cur = cur.next count += 1 node.next = cur.next cur.next = node def remove(self, item) -> None: """刪除連結串列中的一個節點 O(n)""" if self.is_empty(): return pre, cur = None, self.__head while cur.next != self.__head: if cur.elem == item: # 移除頭結點 if cur == self.__head: rear = self.__head while rear.next != self.__head: rear = rear.next self.__head = cur.next rear.next = self.__head # 移除中間節點 else: pre.next = cur.next return # 結束。只remove第一個元素 pre = cur cur = cur.next # 移除尾結點 if cur.elem == item: if cur == self.__head: self.__head = None else: pre.next = self.__head # 或者 pre.next = cur.next def search(self, item) -> bool: """查詢節點是否存在 O(n)""" if self.is_empty(): return False else: cur = self.__head while cur.next != self.__head: if cur.elem == item: return True cur = cur.next return cur.elem == item
```python [s-雙向連結串列] class DoubleLinkList(object): """雙向連結串列"""
def __init__(self, node=None): self.__head = node def is_empty(self) -> bool: """連結串列是否為空 O(1)""" return self.__head is None def length(self) -> int: """連結串列長度 O(n)""" count, cur = 0, self.__head while cur is not None: cur = cur.next # 不要寫錯cur = self.__head.next, self.__next不是活動指標 count += 1 return count def transverse(self) -> '': """遍歷所有節點 O(n)""" cur = self.__head # 不是 self._head while cur is not None: print(cur.elem, end=' ') cur = cur.next return '' def add(self, item) -> None: """頭部新增節點 O(1)""" node = DoubleNode(item) node.next = self.__head self.__head = node if node.next: # 當原連結串列為空時 node.next.prev = node def append(self, item) -> None: """尾部新增節點 O(n)""" node = DoubleNode(item) cur = self.__head if self.is_empty(): self.__head = node else: while cur.next is not None: cur = cur.next cur.next = node node.prev = cur def insert(self, position: int, item) -> None: """ 節點插入到某個位置 O(n) :param position: 0表示第1個位置 :param item: :return: None """ if position <= 0: self.add(item) elif position >= self.length(): self.append(item) else: node = DoubleNode(item) count, cur = 1, self.__head while count < position: cur = cur.next count += 1 node.next = cur.next node.prev = cur cur.next.prev = node cur.next = node def remove(self, item) -> None: """刪除連結串列中的一個節點 O(n)""" cur = self.__head while cur is not None: if cur.elem == item: if cur == self.__head: self.__head = cur.next if self.__head: # 只有一個節點的特殊情況 cur.next.prev = None else: cur.prev.next = cur.next if cur.next: cur.next.prev = cur.prev break # 只remove第一個元素 cur = cur.next def search(self, item) -> bool: """查詢節點是否存在 O(n)""" cur = self.__head while cur is not None: if cur.elem == item: return True cur = cur.next return False ```python [s-雙向迴圈連結串列] class DoubleCycleLinkList(object): """雙向迴圈連結串列""" def __init__(self, node=None): self.__head = node if node: node.next = node node.prev = node def is_empty(self) -> bool: """連結串列是否為空 O(1)""" return self.__head is None def length(self) -> int: """連結串列長度 O(n)""" if self.is_empty(): return 0 count, cur = 1, self.__head while cur.next != self.__head: cur = cur.next # 不要寫錯cur = self.__head.next, self.__next不是活動指標 count += 1 return count def transverse(self) -> '': """遍歷所有節點 O(n)""" if not self.is_empty(): cur = self.__head # 不是 self._head while cur.next != self.__head: print(cur.elem, end=' ') cur = cur.next print(cur.elem, end=' ') return '' def add(self, item) -> None: """頭部新增節點 O(n)""" node = DoubleNode(item) if self.is_empty(): self.__head = node node.next = node node.prev = node else: cur = self.__head while cur.next != self.__head: cur = cur.next # 退出while迴圈之後cur指向尾結點,雙向迴圈連結串列需要改動5個指標 node.next = self.__head # 1.node.next指向原來的頭結點 node.prev = cur # 2.node.prev指向尾結點,當前cur指向的節點 cur.next.prev = node # 3.原來頭結點的prev指向要插入的node self.__head = node # 4.self.__head指向要插入的node cur.next = node # 5.尾結點的next指向要插入的node def append(self, item) -> None: """尾部新增節點 O(n)""" node = DoubleNode(item) if self.is_empty(): self.__head = node node.next = node node.prev = node else: cur = self.__head # 退出while迴圈之後cur指向尾結點,雙向迴圈連結串列需要改動4個指標 while cur.next != self.__head: cur = cur.next cur.next.prev = node # 1.原來頭結點的.prev指向要插入的node cur.next = node # 2.原來尾結點.next指向要插入的node node.prev = cur # 3.node.prev指向原來的尾節點 node.next = self.__head # 4.node.next指向頭結點 def insert(self, position: int, item) -> None: """ 節點插入到某個位置 O(n) :param position: 0表示第1個位置 :param item: :return: None """ if position <= 0: self.add(item) elif position >= self.length(): self.append(item) else: node = DoubleNode(item) count, cur = 1, self.__head while count < position: cur = cur.next count += 1 node.next = cur.next node.prev = cur cur.next.pre = node cur.next = node def remove(self, item) -> None: """刪除連結串列中的一個節點 O(n)""" if self.is_empty(): return cur = self.__head while cur.next != self.__head: if cur.elem == item: # 移除頭結點 if cur == self.__head: cur.prev.next = cur.next cur.next.prev = cur.prev self.__head = cur.next # 移除中間節點 else: cur.prev.next = cur.next cur.next.prev = cur.prev return # 結束。只remove第一個元素 cur = cur.next # 移除尾結點 if cur.elem == item: if cur == self.__head: # 當連結串列只有一個節點時 self.__head = None else: cur.next.prev = cur.prev cur.prev.next = cur.next def search(self, item) -> bool: """查詢節點是否存在 O(n)""" if self.is_empty(): return False else: cur = self.__head while cur.next != self.__head: if cur.elem == item: return True cur = cur.next return cur.elem == item
在以上四種連結串列的實現中,可以發現有的類方法程式碼是重複的,具體重複的方法如下: - 所有的is_empty()
方法都一樣 - 雙向連結串列的length()
, traversing()
, search(item)
實現與單向連結串列 - 雙向迴圈連結串列的length()
, traversing()
, search(item)
實現與單向迴圈連結串列一樣 因此,我們可以使用Python中類的特性:繼承和多型 來簡化程式碼,使用了繼承之後把self.__head
改成self.head
。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# __author__ = 'zhao zi yang'
class Node(object):
"""單節點"""
def __init__(self, elem):
self.elem = elem
self.next = None
class DoubleNode(Node):
"""雙節點"""
def __init__(self, elem):
super(DoubleNode, self).__init__(elem)
self.prev = None
class SingleLinkList(object):
"""單鏈表"""
def __init__(self, node=None):
self.head = node
def is_empty(self) -> bool:
"""連結串列是否為空 O(1)"""
return self.head is None
def length(self) -> int:
"""連結串列長度 O(n)"""
count, cur = 0, self.head
while cur is not None:
cur = cur.next # 不要寫錯cur = self.head.next, self.__next不是活動指標
count += 1
return count
def traversing(self) -> '':
"""遍歷所有節點 O(n)"""
cur = self.head # 不是 self._head
while cur is not None:
print(cur.elem, end=' ')
cur = cur.next
return ''
def add(self, item) -> None:
"""頭部新增節點 O(1)"""
node = Node(item)
node.next = self.head
self.head = node
def append(self, item) -> None:
"""尾部新增節點 O(n)"""
node = Node(item)
cur = self.head
if self.is_empty():
self.head = node
else:
while cur.next is not None:
cur = cur.next
cur.next = node
def insert(self, position: int, item) -> None:
"""
節點插入到某個位置 O(n)
:param position: 0表示第1個位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = Node(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
cur.next = node
def remove(self, item) -> None:
"""刪除連結串列中的一個節點 O(n)"""
pre, cur = None, self.head
while cur is not None:
if cur.elem == item:
if cur == self.head:
self.head = cur.next
break # 只remove第一個元素
pre.next = cur.next
break
pre = cur
cur = cur.next
def search(self, item) -> bool:
"""查詢節點是否存在 O(n)"""
cur = self.head
while cur is not None:
if cur.elem == item:
return True
cur = cur.next
return False
class SingleCycleLinkList(SingleLinkList):
"""單向迴圈連結串列"""
def __init__(self, node=None):
if node:
node.next = node
super(SingleCycleLinkList, self).__init__(node=node)
def length(self) -> int:
"""連結串列長度 O(n)"""
if self.is_empty():
return 0
count, cur = 1, self.head
while cur.next != self.head:
cur = cur.next # 不要寫錯cur = self.head.next, self.__next不是活動指標
count += 1
return count
def traversing(self) -> '':
"""遍歷所有節點 O(n)"""
if not self.is_empty():
cur = self.head # 不是 self._head
while cur.next != self.head:
print(cur.elem, end=' ')
cur = cur.next
print(cur.elem, end=' ')
return ''
def add(self, item) -> None:
"""頭部新增節點 O(n)"""
node = Node(item)
if self.is_empty():
self.head = node
node.next = node
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
# 退出while迴圈之後cur指向尾結點
node.next = self.head
self.head = node
cur.next = self.head
def append(self, item) -> None:
"""尾部新增節點 O(n)"""
node = Node(item)
if self.is_empty():
self.head = node
node.next = node
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
cur.next = node
node.next = self.head
def insert(self, position: int, item) -> None:
"""
節點插入到某個位置 O(n)
:param position: 0表示第1個位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = Node(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
cur.next = node
def remove(self, item) -> None:
"""刪除連結串列中的一個節點 O(n)"""
if self.is_empty():
return
pre, cur = None, self.head
while cur.next != self.head:
if cur.elem == item:
# 移除頭結點
if cur == self.head:
rear = self.head
while rear.next != self.head:
rear = rear.next
self.head = cur.next
rear.next = self.head
# 移除中間節點
else:
pre.next = cur.next
return # 結束。只remove第一個元素
pre = cur
cur = cur.next
# 移除尾結點
if cur.elem == item:
if cur == self.head:
self.head = None
else:
pre.next = self.head # 或者 pre.next = cur.next
def search(self, item) -> bool:
"""查詢節點是否存在 O(n)"""
if self.is_empty():
return False
else:
cur = self.head
while cur.next != self.head:
if cur.elem == item:
return True
cur = cur.next
return cur.elem == item
class DoubleLinkList(SingleLinkList):
"""雙鏈表"""
def add(self, item) -> None:
"""頭部新增節點 O(1)"""
node = DoubleNode(item)
node.next = self.head
self.head = node
if node.next: # 當原連結串列為空時
node.next.prev = node
def append(self, item) -> None:
"""尾部新增節點 O(n)"""
node = DoubleNode(item)
cur = self.head
if self.is_empty():
self.head = node
else:
while cur.next is not None:
cur = cur.next
cur.next = node
node.prev = cur
def insert(self, position: int, item) -> None:
"""
節點插入到某個位置 O(n)
:param position: 0表示第1個位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = DoubleNode(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
node.prev = cur
cur.next.prev = node
cur.next = node
def remove(self, item) -> None:
"""刪除連結串列中的一個節點 O(n)"""
cur = self.head
while cur is not None:
if cur.elem == item:
if cur == self.head:
self.head = cur.next
if self.head: # 只有一個節點的特殊情況
cur.next.prev = None
else:
cur.prev.next = cur.next
if cur.next:
cur.next.prev = cur.prev
break # 只remove第一個元素
cur = cur.next
class DoubleCycleLinkList(SingleCycleLinkList):
"""雙向迴圈連結串列"""
def __init__(self, node=None):
if node:
node.next = node
node.prev = node
super(DoubleCycleLinkList, self).__init__(node=node)
def add(self, item) -> None:
"""頭部新增節點 O(n)"""
node = DoubleNode(item)
if self.is_empty():
self.head = node
node.next = node
node.prev = node
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
# 退出while迴圈之後cur指向尾結點,雙向迴圈連結串列需要改動5個指標
node.next = self.head # 1.node.next指向原來的頭結點
node.prev = cur # 2.node.prev指向尾結點,當前cur指向的節點
cur.next.prev = node # 3.原來頭結點的prev指向要插入的node
self.head = node # 4.self.head指向要插入的node
cur.next = node # 5.尾結點的next指向要插入的node
def append(self, item) -> None:
"""尾部新增節點 O(n)"""
node = DoubleNode(item)
if self.is_empty():
self.head = node
node.next = node
node.prev = node
else:
cur = self.head
# 退出while迴圈之後cur指向尾結點,雙向迴圈連結串列需要改動4個指標
while cur.next != self.head:
cur = cur.next
cur.next.prev = node # 1.原來頭結點的.prev指向要插入的node
cur.next = node # 2.原來尾結點.next指向要插入的node
node.prev = cur # 3.node.prev指向原來的尾節點
node.next = self.head # 4.node.next指向頭結點
def insert(self, position: int, item) -> None:
"""
節點插入到某個位置 O(n)
:param position: 0表示第1個位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = DoubleNode(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
node.prev = cur
cur.next.pre = node
cur.next = node
def remove(self, item) -> None:
"""刪除連結串列中的一個節點 O(n)"""
if self.is_empty():
return
cur = self.head
while cur.next != self.head:
if cur.elem == item:
# 移除頭結點
if cur == self.head:
cur.prev.next = cur.next
cur.next.prev = cur.prev
self.head = cur.next
# 移除中間節點
else:
cur.prev.next = cur.next
cur.next.prev = cur.prev
return # 結束。只remove第一個元素
cur = cur.next
# 移除尾結點
if cur.elem == item:
if cur == self.head: # 當連結串列只有一個節點時
self.head = None
else:
cur.next.prev = cur.prev
cur.prev.next = cur.next
if __name__ == '__main__':
print("----single_link_list-----")
single_link_list = SingleLinkList()
single_link_list.remove('test')
print(single_link_list.is_empty(), single_link_list.length())
single_link_list.insert(-1, 'zhao')
print(single_link_list.is_empty(), single_link_list.length())
single_link_list.insert(3, 'zi')
print(single_link_list.length())
single_link_list.append('yang')
single_link_list.add("head")
single_link_list.insert(4, "tail")
print(single_link_list.traversing())
single_link_list.remove(1)
print(single_link_list.traversing())
single_link_list.remove("head")
print(single_link_list.traversing())
single_link_list.remove("tail")
print(single_link_list.traversing())
single_link_list.remove('zi')
print(single_link_list.traversing())
print("n----single_cycle_link_list-----")
single_cycle_link_list = SingleCycleLinkList()
single_cycle_link_list.remove('test')
print(single_cycle_link_list.is_empty(), single_cycle_link_list.length())
single_cycle_link_list.insert(-1, 'zhao')
print(single_cycle_link_list.is_empty(), single_cycle_link_list.length())
single_cycle_link_list.insert(3, 'zi')
print(single_cycle_link_list.length())
single_cycle_link_list.append('yang')
single_cycle_link_list.add("head")
single_cycle_link_list.insert(4, "tail")
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove(1)
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove("head")
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove("tail")
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove('zi')
print(single_cycle_link_list.traversing())
print("n----double_link_list-----")
double_link_list = DoubleLinkList()
double_link_list.remove('test')
print(double_link_list.is_empty(), double_link_list.length())
double_link_list.insert(-1, 'zhao')
print(double_link_list.is_empty(), double_link_list.length())
double_link_list.insert(3, 'zi')
print(double_link_list.length())
double_link_list.append('yang')
double_link_list.add("head")
double_link_list.insert(4, "tail")
print(double_link_list.traversing())
double_link_list.remove(1)
print(double_link_list.traversing())
double_link_list.remove("head")
print(double_link_list.traversing())
double_link_list.remove("tail")
print(double_link_list.traversing())
double_link_list.remove('zi')
print(double_link_list.traversing())
print("n----double_cycle_link_list-----")
double_cycle_link_list = DoubleCycleLinkList()
double_cycle_link_list.remove('test')
print(double_cycle_link_list.is_empty(), double_cycle_link_list.length())
double_cycle_link_list.insert(-1, 'zhao')
print(double_cycle_link_list.is_empty(), double_cycle_link_list.length())
double_cycle_link_list.insert(3, 'zi')
print(double_cycle_link_list.length())
double_cycle_link_list.append('yang')
double_cycle_link_list.add("head")
double_cycle_link_list.insert(4, "tail")
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove(1)
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove("head")
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove("tail")
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove('zi')
print(double_cycle_link_list.traversing())
結果執行如下:
----single_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang
----single_cycle_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang
----double_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang
----double_cycle_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang