1. 程式人生 > >用 python 學習資料結構(二)雙向連結串列

用 python 學習資料結構(二)雙向連結串列

##一、相比單向連結串列,雙向連結串列的優勢 雙向連結串列的每個節點儲存了前一個節點和後一個節點的引用(指標),到達某個節點是,可以向前或者向後遍歷,提高了操作的效率。比如,insertBefore(nodeA, value) 操作,可以一步完成,而不需要先查詢 nodeA 的前序節點。

newNode = ListNode(value)
nodeA.prev.next = newNode
newNode.prev = nodeA.prev
newNode.next = nodeA
nodeA.prev = newNode

##二、關於List 的遍歷訪問,使用迭代器。 可以把迭代器理解為指向 List 的一個遊標,這個遊標可以向前或者向後(一般是從前向後遍歷)遍歷整個 List。 如果我們的 List 想要支援迭代訪問,比如 for val in listA: xxx, 就必須實現迭代器,必須要實現自己的迭代器類和迭代方法。

##三、語言描述總數太抽象,直接看程式碼吧。 如果發現問題或者有疑問,歡迎與我討論。看完程式碼,相信你對 python 的迭代器以及可迭代物件有了新的認識。

歡迎加入我們免費的 python 學習交流社群,請先掃描群主二維碼,加群主為好友,然後申請入群。群內技術大牛每日交流,即時答疑。也歡迎關注我們的技術公眾號,會定期推送學習材料(簡書markdown 圖片尺寸好像不能調整,醜哭)。

# -*- coding: utf-8 -*-

# 定義節點類,儲存資料和前後物件的引用
class ListNode():
	def __init__(self,value):
		self.value = value
		self.next = None
		self.prev = None

# 根據 python 的迭代器規範,定義一個迭代器
class ListIterator():
	def __init__(self, l):
		self.list = l
		self.cur = l.head

	def __iter__(self):
		return self

	# next 函式,用來返回下一個資料
	def next(self):
		if self.cur.next == l.tail:
			# 如果迭代結束了,按照規範需要丟擲 StopIteration 異常
			raise StopIteration()
		else:
			self.cur = self.cur.next
			return self.cur.value

# 定義List類,實現可迭代操作的介面
class List():
	def __init__(self):
		self.head = ListNode(0)
		self.tail = ListNode(0)
		self.head.next = self.tail
		self.tail.prev = self.head
		self.count = 0

	def __len__(self):
		return self.count

	def __iter__(self):
		return ListIterator(self)

	# 插入列表尾部	
	def append(self, value):
		return self.insertBefore(self.tail, value)

	# 插入列表頭部
	def addFirst(self, value):
		return self.insertAfter(self.head, value)

	def find(self, value):
		cur = self.head.next
		while cur and cur.value != value:
			cur = cur.next
		return cur

	# 刪除一個節點
	def remove(self, node):
		node.prev.next = node.next
		node.next.prev = node.prev
		self.count -= 1

	# 在某個節點前面插入新的資料
	def insertBefore(self, node, value):
		newNode = ListNode(value)
		node.prev.next = newNode
		newNode.prev = node.prev
		newNode.next = node
		node.prev = newNode
		self.count+=1
		return newNode

	# 有沒有發現雙向連結串列的插入操作實現起來非常的簡單了	
	def insertAfter(self, node, value):
		return self.insertBefore(node.next, value)

if __name__ == '__main__':
	# append
	l = List()
	l.append(1)
	l.append(2)
	l.append(3)

	# find
	v1 = l.find(1)
	v2 = l.find(2)
	v3 = l.find(3)
	print(v1.value)
	print(v2.value)

	#remove
	l.remove(v1)
	l.remove(v2)

	#insert before 
	v22 = l.insertBefore(v3, -2)
	v33 = l.insertBefore(v22, -3)

    #insert after
	v4 = l.insertAfter(v3, 4)
	v5 = l.insertAfter(v4, 5)

    #count 5
	print(len(l))

    #print list -3, -2, 3, 4, 5
	for val in l: print val,