一、單向鏈表
(1) 鏈表的定義
鏈表是一種常見的數據結構,是一種線性表,但是不像順序表一樣連續存儲數據,而是再每一個節點(數據存儲單元)裏存放下一個節點的位置信息(即地址)。
"""
鏈表的實現: list = [100, 200, 300]
| 內存 | 數據區| 下一個節點地址|
地址1:0x11 100 0x34
地址2:0x34 200 0x20
地址3:0x20 300 None
那麼列表實現就如圖所示:
"""
(2)爲什麼需要鏈表
- 順序表的構建需要預先知道數據大小來申請一塊連續的存儲空間,而在進行擴充時又需要進行數據的搬遷,所以使用起來不是很靈活,引入鏈表結構可以充分利用計算機內存空間,實現靈活的動態管理。
- 另外,如果現在需要存儲一個較大的數據,連續的內存不夠用,也可以採用鏈表進行分散的存儲,然後將數據鏈接在一起。
(3)單向鏈表
- 單向鏈表也叫單鏈表,是鏈表中最簡單的一種形式,它的每個節點包含兩個域,一個信息域(元素域)和一個鏈接域,最後一個節點的鏈表域則指向一個空值。
- 單向鏈表結點:
- 單向鏈表:
- 變量P指向鏈表的頭結點的位置,從P出發能找到表中的任意結點
(4)單向循環列表
單向循環鏈表是將單向鏈表尾結點的next 指向頭結點
(5)雙向鏈表
- 概述
雙向鏈表或者雙面鏈表,每個結點有兩個鏈表,一個指向前一個結點,當此結點爲第一個結點時,指向空,而另一個指向下一個結點,當此結點爲最後一個結點時指向空值。
2. 雙向鏈表結構 其中:P爲前趨結點 N 爲後繼結點
二、單向鏈表實現
class Node(object):
"""節點"""
def __init__(self, elem):
super(Node, self).__init__()
# 元素
self.elem = elem
# 下一個節點地址
self.next = None
class SingleLinkList(object):
"""單鏈表:實現增、刪、改、查"""
def __init__(self, node=None):
self.__head = node
def is_empty(self):
"""鏈表爲是否爲空 """
return self.__head is None
def length(self):
"""鏈表長度"""
cur = self.__head # 定義遊標cur,用來遍歷節點
count = 0 # 統計節點個數
while cur is not None:
count += 1
cur = cur.next
return count
def travel(self):
""" 遍歷整個鏈表"""
cur = self.__head
while cur is not None:
print("當前的節點是:%s" % cur.elem)
cur = cur.next
def add(self, item):
"""鏈表頭部添加元素,頭插法"""
node = Node(item)
node.next = self.__head
self.__head = 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
def insert(self, pos, item):
"""
指定位置添加元素 pos: 位置 item:元素
pos: 從0開始
"""
if pos <= 0:
self.add(item)
elif pos > (self.length() - 1):
self.append(item)
else:
pre = self.__head # 前一個位置
count = 0
while count < (pos - 1):
count += 1
pre = pre.next
# 當循環退出後pre = pos -1 的位置
node = Node(item)
node.next = pre.next
pre.next = node
def remove(self, item):
"""
刪除節點 : 考慮列表爲空,刪除列表的頭節點, 只有一個節點,尾部的節點
"""
cur = self.__head
pre = None
while cur is not None:
if cur.elem == item:
# 判斷次節點是否爲頭節點
if cur == self.__head:
self.__head = cur.next
else:
pre.next = cur.next
break
else:
pre = cur
cur = cur.next
def search(self, item):
"""查找節點是否存在"""
cur = self.__head
while cur is not None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
if __name__ == '__main__':
ll = SingleLinkList()
print(ll.is_empty())
ll.append(1)
ll.append(100)
ll.append(200)
ll.travel()
ll.remove(1)
ll.travel()
二、單向循環列表實現
class Node(object):
def __init__(self, item):
"""結點"""
self.elem = item
self.next = None
class SingleLinkCircle(object):
"""單向循環鏈表"""
def __init__(self, node=None):
self.__head = node
if node:
node.next = node
def is_empty(self):
"""判斷是否爲空"""
return self.__head is None
def length(self):
"""判斷鏈表長度"""
if self.is_empty():
return 0
else:
cur = self.__head
count = 1
while cur.next != self.__head:
count += 1
cur = cur.next
return count
def travel(self):
"""遍歷鏈表"""
if self.is_empty():
print("")
else:
cur = self.__head
while cur.next != self.__head:
print(cur.elem, end=" ")
cur = cur.next
# 循環結束打印最後一個結點
print(cur.elem)
def add(self, item):
"""在頭部添加結點"""
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
node.next = self.__head
self.__head = node
cur.next = node
def append(self, item):
"""在尾部添加結點"""
node = Node(item)
if self.is_empty():
self.__head = node
node.next = self.__head
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
node.next = self.__head
cur.next = node
def insert(self, pos, item):
"""在特定位置插入結點"""
if pos <= 0:
self.add(item)
elif pos > (self.length() - 1):
self.append(item)
else:
pre = self.__head
count = 0
while count < (pos - 1):
count += 1
pre = pre.next
node = Node(item)
node.next = pre.next
pre.next = node
def remove(self, item):
"""刪除指定結點"""
cur = self.__head
pre = None
if self.is_empty():
return
while cur.next != self.__head:
if cur.elem == item:
# 頭結點
if cur == self.__head:
# 找到尾結點
finall = self.__head
while finall.next != self.__head:
finall = finall.next
# 將尾結點的地址指向要刪除結點的下一個結點
finall.next = cur.next
self.__head = cur.next
else:
# 中間結點
pre.next = cur.next
return # 這裏注意,刪除完成後讓程序直接退出,不用break
else:
pre = cur
cur = cur.next
# 判斷刪除的是尾結點
if cur.elem == item:
if cur == self.__head:
self.__head = None
else:
pre.next = self.__head
def search(self, item):
"""查找結點"""
if self.is_empty():
return False
else:
cur = self.__head
while cur.next != self.__head:
if cur.elem == item:
return True
cur = cur.next
if cur.elem == item:
return True
return False
if __name__ == '__main__':
ll = SingleLinkCircle()
ll.add(3)
ll.add(4)
print("test add()\n")
ll.travel()
ll.append(5)
ll.append(6)
print("test append()\n")
ll.travel()
ll.insert(2, 9)
ll.insert(3, 0)
print("test insert()\n")
ll.travel()
ll.remove(4)
ll.remove(6)
print("test remove()\n")
ll.travel()
print("test search()\n")
ll.search(5)
print(ll.length())
三、雙向鏈表實現
class Node(object):
"""node"""
def __init__(self, item):
self.elem = item
self.prev = None
self.next = None
class DoubleLinkList(object):
def __init__(self, node=None):
self.__head = node
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 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)
"""method one"""
# node.next = self.__head
# self.__head = node
# node.next.prev = node
"""method two"""
self.__head.prev = node
self.__head = 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):
node = Node(item)
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
cur = self.__head
count = 0
while count < pos:
count += 1
cur = cur.next
# node.prev = cur
# node.next = cur.next
# cur = node
# cur.next = node
""" method"""
node.next = cur
node.prev = cur.prev
cur.prev = node
node.prev.next = 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:
# only one node
cur.next.prev = None
else:
cur.prev.next = cur.next
if cur.next:
# finally node
cur.next.prev = cur.prev
break
else:
cur = cur.next
def search(self, item):
cur = self.__head
while cur is not None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
if __name__ == '__main__':
lk = DoubleLinkList()
lk.append(2)
lk.append(3)
lk.insert(1, 0)
lk.append(4)
lk.append(5)
lk.add(6)
lk.travel()
lk.remove(6)
lk.travel()
print(lk.length())