01.线性表
顺序表
python中的list和tuple就采用了顺序表的实现技术
tuple是不变的表,因此不支持改变其内部状态的任何操作
list是一种元素个数可变的线性表,可以加入和删除元素,在各种操作中维持已有元素的顺序
list对象无法设置容量的操作
if __name__ == '__main__': lt = list([1, 3, 2]) print(len(lt)) # 3 print(lt) # [1, 3, 2] # 元素顺序倒置 lt.reverse() print(lt) # [2, 3, 1] # 排序 lt.sort() print(lt) # [1, 2, 3] # 清除表中所有元素 lt.clear() print(len(lt)) # 0
单链表:
单链表头部添加元素:
class LNode: """表节点""" # next_防止与标准函数next重名 def __init__(self, elem, next_=None): self.elem = elem self.next = next_ class LinkedListUnderflow(ValueError): pass class LList: """单链表""" def __init__(self): self._head = None def is_empty(self): """链表是否为空""" return self._head is None def __len__(self): """链表长度""" count = 0 p = self._head while p: count += 1 p = p.next return count def prepend(self, elem): """表头插入数据""" # node = LNode(elem) # node.next = self._head # self._head = node # 合并为一句 self._head = LNode(elem, self._head) def pop(self): """删除头一个元素""" if self._head is None: # 无结点,抛出异常 raise LinkedListUnderflow("in pop") e = self._head.elem self._head = self._head.next return e def append(self, elem): """尾部添加元素""" if self._head is None: self._head = LNode(elem) return p = self._head while p.next is not None: p = p.next p.next = LNode(elem) def printall(self): p = self._head while p: print(p.elem, end='') if p.next: print(', ', end='') p = p.next print('') def for_each(self, proc): """遍历函数,proc的参数应该是可以作用于表元素的操作函数,如:print""" p = self._head while p: proc(p.elem) p = p.next def elements(self): """迭代器""" p = self._head while p: yield p.elem p = p.next def find(self, pred): """返回符合条件的第一个""" p = self._head while p is not None: if pred(p.elem): return p.elem p = p.next def filter(self, pred): """筛选生成器""" p = self._head while p is not None: if pred(p.elem): yield p.elem p = p.next if __name__ == '__main__': llist1 = LNode(1) p = llist1 for i in range(2, 11): p.next = LNode(i) p = p.next p = llist1 # 可简写 while p: while p is not None: print(p.elem) p = p.next mlist1 = LList() for i in range(3): mlist1.prepend(i) for i in range(4, 7): mlist1.append(i) mlist1.printall() # 2, 1, 0, 4, 5, 6 mlist1.for_each(print) print("-------") for x in mlist1.elements(): print(x, end=' ') # 2 1 0 4 5 6 print("-------") print(mlist1.find(lambda z: z > 3)) # 4 print("-------") for x in mlist1.filter(lambda z: z > 3): print(x, end=' ') # 4 5 6 print("-------") print(len(mlist1)) # 6
补充单链表的排序:
def sort(self): """从小到大排序 通过移动表中元素实现""" if self._head is None: return crt = self._head.next # 待插入的点 while crt: x = crt.elem p = self._head while p is not crt and p.elem <= x: p = p.next while p is not crt: y = p.elem p.elem = x x = y p = p.next crt.elem = x # 回填最后一个元素 crt = crt.next def sort2(self): """从小到大排序 通过调整结点之间的实现""" p = self._head if p is None or p.next is None: return rem = p.next # 待插入的点 p.next = None # 第一个元素作为排序好的元素 while rem: p = self._head # 每次从排好的第一个开始比较 q = None while p and p.elem <= rem.elem: # 新插入的大遍历放排序好的最后 q = p p = p.next if q is None: # 新插入的最小,所有作为头 self._head = rem else: q.next = rem q = rem rem = rem.next q.next = p
带有尾节点引用的单链表:
头部添加元素:
反转:
class LList2(LList): """带有尾节点引用的单链表""" def __init__(self): # 相当于LList.__init__() super(LList2, self).__init__() self._rear = None def prepend(self, elem): """表头插入数据""" if self._head is None: self._head = LNode(elem, self._head) self._rear = self._head else: self._head = LNode(elem, self._head) def append(self, elem): """尾部添加元素""" if self._head is None: self._head = LNode(elem, self._head) self._rear = self._head else: self._rear.next = LNode(elem) self._rear = self._rear.next def pop_last(self): """弹出末尾元素""" if self._head is None: raise LinkedListUnderflow("in pop_last") p = self._head # 只有一个元素 # 表判断空用_head的值,所有删除最后一个结点使表变空时,不需要给_rear赋值None if p.next is None: e = p.elem self._head = None return e while p.next.next: p = p.next e = p.next.elem p.next = None self._rear = p return e
def rev(self):
"""反转"""
p = None
if self._head:
self._rear = self._head
while self._head:
q = self._head
self._head = q.next
q.next = p
p = q
self._head = p
if __name__ == '__main__':
mlist1 = LList2()
mlist1.prepend(1)
mlist1.prepend(2)
for i in range(3, 5):
mlist1.append(i)
for i in mlist1.elements():
print(i, end=' ') # 2 1 3 4
print("---------")
print(mlist1.pop_last()) # 4
循环单链表:
class LNode: """表节点""" # next_防止与标准函数next重名 def __init__(self, elem, next_=None): self.elem = elem self.next = next_ class LinkedListUnderflow(ValueError): pass class LCList: """循环单链表""" def __init__(self): self._rear = None def is_empty(self): return self._rear is None def prepend(self, elem): """首端插入""" p = LNode(elem) if self._rear is None: p.next = p self._rear = p else: p.next = self._rear.next self._rear.next = p def append(self, elem): """尾端插入""" self.prepend(elem) self._rear = self._rear.next def pop(self): """首端弹出""" if self._rear is None: raise LinkedListUnderflow("in pop of LCList") p = self._rear.next # 只有一个元素 if self._rear is p: self._rear = None else: self._rear.next = p.next return p.elem def printall(self): """输出表元素""" if self.is_empty(): return p = self._rear.next while 1: print(p.elem) if p is self._rear: break p = p.next if __name__ == '__main__': mlclist1 = LCList() mlclist1.prepend(1) mlclist1.prepend(2) for i in range(3, 5): mlclist1.append(i) mlclist1.printall() # 2 # 1 # 3 # 4 print("---------") print(mlclist1.pop()) # 2
双链表:
class DLNode: """双链表节点""" def __init__(self, elem, prev=None, next_=None): self.elem = elem self.prev = prev self.next = next_ class LinkedListUnderflow(ValueError): pass class DLLList: """双链表""" def __init__(self): self._head = None self._rear = None def is_empty(self): return self._head is None def prepend(self, elem): """首端插入""" p = DLNode(elem, None, self._head) if self._head is None: self._rear = p else: p.next.prev = p self._head = p def append(self, elem): """尾端插入""" p = DLNode(elem, self._rear, None) if self._head is None: self._head = p else: p.prev.next = p self._rear = p def pop(self): """首端弹出""" if self._head is None: raise LinkedListUnderflow("in pop of LCList") e = self._head.elem self._head = self._head.next if self._head: self._head.prev = None return e def pop_last(self): if self._head is None: raise LinkedListUnderflow("in pop_last of LCList") e = self._rear.elem self._rear = self._rear.prev if self._rear is None: self._head = None else: self._rear.next = None return e def printall(self): """输出表元素""" if self.is_empty(): return p = self._head while 1: print(p.elem) if p is self._rear: break p = p.next if __name__ == '__main__': mlclist1 = DLLList() mlclist1.prepend(1) mlclist1.prepend(2) for i in range(3, 5): mlclist1.append(i) mlclist1.printall() # 2 # 1 # 3 # 4 print("---------") print(mlclist1.pop()) # 2 print(mlclist1.pop_last()) # 4