鏈表是實現了數據之間保持邏輯順序,但存儲空間不連續的數據結構。
相對於單向鏈表,雙向鏈表多了一個指向前面一個節點的指針域。
鏈表查詢效率較慢,由於查詢的時候須要移動指針一個一個找。
雙向鏈表新增和刪除元素效率較高,由於鏈表會記錄前一個節點和後一個節點。html
class Node: def __init__(self, item, next=None, prev=None): self.item = item self.next = next self.prev = prev def __str__(self): return '<prev: {} <- node: {} -> next: {}>'.format(self.prev.item if self.prev else None, self.item, self.next.item if self.next else None) def __repr__(self): return str(self.item) class LinkedList: def __init__(self): self.head = None self.tail = None self.size = 0 def append(self, item): node = Node(item) # 若是head節點爲空,表示鏈表爲空 if self.head is None: self.head = node self.tail = node else: self.tail.next = node node.prev = self.tail self.tail = node self.size += 1 return self def index(self, item): for i, node in enumerate(self): if item == node.item: return i else: raise ValueError('item does not exist') def insert(self, index, item): if index < 0: raise IndexError # 若是找到就將current指向對應位置的節點,繼續後面的操做 # 若是沒有找到(鏈表爲空或者索引超界),則追加並當即返回,後面的操做將不會執行 for i, node in enumerate(self): if i == index: current = node break else: self.append(item) return node = Node(item) prev = current.prev # 從頭部插入 if prev is None: node.next = current current.prev = node self.head = node # 從中間插入(尾部插入即追加,上面已經實現) else: node.next = current node.prev = prev prev.next = node current.prev = node self.size += 1 def pop(self): # 若是尾部爲空,則表示鏈表爲空 if self.tail is None: raise Exception('empty') node = self.tail item = node.item prev = node.prev # 若是尾部節點沒有前節點,則表示鏈表只有一個元素 if prev is None: self.head = None self.tail = None # 剩下就是有多個節點的狀況 else: prev.next = None self.tail = prev self.size -= 1 return item def remove(self, index): if index < 0: raise IndexError('does not support negative index') # 若是鏈表爲空,則拋出異常 if self.head is None: raise Exception('empty') # 若是找到就將current指向對應位置的節點,繼續後面的操做 # 若是沒有找到(鏈表爲空或者索引超界),則拋出異常 for i, node in enumerate(self): if i == index: current = node break else: raise IndexError('index out of range') prev = current.prev next = current.next # 若是current沒有前節點也沒有後節點,表示只有一個節點 if prev is None and next is None: self.head = None self.tail = None # 若是不止一個節點,且若是current沒有前節點,表示current是head elif prev is None: next.prev = None self.head = next # 若是不止一個節點、current不是head,且若是current沒有後節點,表示current是tail elif next is None: prev.next = None self.tail = prev # 剩下就是多節點從中間remove的狀況 else: prev.next = next next.prev = prev self.size -= 1 # def iternodes(self, reverse=False): # current = self.head if not reverse else self.tail # while current: # yield current # current = current.next if not reverse else current.head def clear(self): for node in self: node.prev = None node.tail = None self.head = None self.tail = None self.size = 0 def __iter__(self): current = self.head while current: yield current current = current.next def __reversed__(self): current = self.tail while current: yield current current = current.prev def __len__(self): # current = self.head # count = 0 # while current: # count += 1 # current = current.next # return count return self.size def __getitem__(self, key): # 支持負索引 obj = reversed(self) if key < 0 else self start = 1 if key < 0 else 0 for i, node in enumerate(obj, start): if abs(key) == i: return node else: raise IndexError('index out of range') def __setitem__(self, key, value): # for i, node in enumerate(self): # if key == i: # node.item = value # else: # self.append(value) self[key].item = value linklist = LinkedList() # 測試append() for i in range(10): linklist.append(i) # 測試__iter__ for node in linklist: print(node) # 測試__reversed__ for node in reversed(linklist): print(node) # 測試__len__ print(len(linklist)) # 測試index() print(linklist.index(3)) # 測試insert() linklist.insert(0, 0) print(list(linklist)) # 測試pop() print(linklist.pop()) # 測試__getitem__ print(linklist[3]) # print(linklist[13]) print(linklist[-1]) # 測試__setitem__ linklist[5] = 15 print(list(linklist)) # 測試clear() linklist.clear() print(list(linklist)) print(len(linklist))
參考:
http://zhaochj.github.io/2016/05/12/2016-05-12-數據結構-鏈表/
http://www.javashuo.com/article/p-aoofxqlq-hx.html
http://blog.suchasplus.com/2011/03/why-python-Standard-library-does-not-implement-the-list.html
https://www.zhihu.com/question/55721190node