链表是实现了数据之间保持逻辑顺序,但存储空间不连续的数据结构。
相对于单向链表,双向链表多了一个指向前面一个节点的指针域。
链表查询效率较慢,由于查询的时候须要移动指针一个一个找。
双向链表新增和删除元素效率较高,由于链表会记录前一个节点和后一个节点。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