使用Python实现常见的数据结构
队列
# 队列 class Queue(object): def __init__(self): self.items= [] # 是否为空 @property def is_empty(self): return self.items == [] # 进队列 def enqueue(self,item): self.items.insert(0,item) # 出队列 def dequeue(self): return self.items.pop() # 队列大小 @property def size(self): return len(self.items) if __name__ == '__main__': q = Queue() print(f"q is empty? <{q.is_empty}>") q.enqueue("whw1") q.enqueue("whw2") q.enqueue("whw3") print(f"q is empty? <{q.is_empty}>") print(f"q's size is {q.size}") print(q.dequeue()) print(f"q's size is {q.size}")
双端队列
# 双端队列 class Dqueue(object): def __init__(self): self.items = [] # 判断是否为空 @property def is_empty(self): return self.items == [] # 在头部添加元素 def add_front(self,item): self.items.insert(0,item) # 在队尾添加元素 def add_end(self,item): self.items.append(item) # 从头部删除元素 def remove_front(self): return self.items.pop(0) # 从尾部删除元素 def remove_end(self): return self.items.pop() # 队列的大小 @property def size(self): return len(self.items) if __name__ == '__main__': dq = Dqueue() print(f"dq is empty? <{dq.is_empty}>") dq.add_front("whw1") dq.add_front("whw2") print(f"dq is empty? <{dq.is_empty}>") print(f"dq's size: {dq.size}") print(dq.remove_front()) dq.add_end("huoying1") dq.add_end("huoying2") print(dq.remove_end()) print(f"dq's size is: {dq.size}")
双端链表
# 双端链表节点 class Node(object): def __init__(self,item): self._item = item self._next = None self._prev = None # 双端链表 class DoubLinkedList(object): def __init__(self): self._head = None # 是否为空 @property def is_empty(self)->bool: return self._head is None # 链表长度 @property def length(self)->int: 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._item) cur = cur._next print("DoubLinkedList has been traveled!") # 头部添加元素 def add(self,item): # 要添加的节点 node = Node(item) # 如果是空链表将_head指向node! if self.is_empty: self._head = node else: # 将node的_next指向_head的头节点 node._next = self._head # 将_head的头节点的_prev指向node self._head.prev = node # 最后将_head指向node self._head = node # 尾部添加元素 def append(self,item): node = Node(item) # 空链表将_head指向node! if self.is_empty: self._head = node else: # 先移动链表到尾部 cur = self._head while cur._next is not None: cur = cur._next # 将尾节点的_next指向node,遍历完后cur暂时是尾节点 cur._next = node # 将node的prev指向cur,此时node就是尾节点了 node._prev = cur # 查找元素是否存在 def search(self,item)->bool: cur = self._head while cur is not None: if cur._item == item: return True cur = cur._next # 没找到返回False return False ### 指定位置插入节点 def insert(self,pos,item): # 头部添加 if pos <= 0: self.add(item) # 尾部添加 elif pos >= self.length: self.append(item) # 按照位置添加 else: node = Node(item) cur = self._head count = 0 # 挪动到指定位置的前一个位置 while count < (pos-1): count += 1 cur = cur._next # 将node的prev指向cur,此时cur是指定位置的上一个元素! node._prev = cur # 将node的_next指向cur的下一个节点 node._next = cur._next # 再将cur的下一个节点的_prev指向node cur._next._prev = node # 最后将cur的next指向node cur._next = node ### 删除元素 def remove(self,item): # 空链表直接返回None if self.is_empty: return cur = self._head # 第一个元素就是要删除的item的话 if cur._item == item: # 如果链表只有一个节点,直接让_head为None即可 if cur._next is None: self._head = None else: # 将第二个节点的prev设置为None cur._next._prev = None # 将_head指向第二个节点 self._head = cur._next return # 遍历链表 while cur is not None: if cur._item == item: # 注意这里需要判断一下cur是否是最后一个节点,最后一个节点的_next是None,None没有_prev if cur._next is not None: # 将cur的前一个节点的_next指向cur的下一个节点 cur._prev._next = cur._next # 将cur的后一个节点的_prev指向cur的前一个节点 cur._next._prev = cur._prev break # 正好删除的是最后一个节点 else: # 直接让最后一个节点的上一个节点的_next指向None,注意break! cur._prev._next = None break else: cur = cur._next # 如果没有删除的元素,什么也不做! if __name__ == '__main__': lst = DoubLinkedList() print(f"lst is empty? <{lst.is_empty}>") lst.add(1) lst.add(2) lst.travel() lst.append(33) lst.append(44) lst.travel() lst.insert(2,"OK") lst.travel() print(f"lst's length is {lst.length}") lst.remove(2) lst.remove(33) lst.remove(44) lst.travel() print(f"lst is empty? <{lst.is_empty}>") print(f"Does OK in lst? <{lst.search('OK')}>") print(f"Does 666 in lst? <{lst.search('666')}>")
单链表
# coding:utf-8 # 单链表的节点 class SingleNode(object): def __init__(self,item): # self._item存放元素 self._item = item # self._next是下一个节点的标识 self._next = None # 单链表 class SingleLinkList(object): def __init__(self): self._head = None # 判断链表是否为空 @property def is_empty(self)->bool: return self._head is None # 求链表的长度 @property def length(self)->int: # cur一开始指向头节点 cur = self._head count = 0 # 注意尾节点也指向None while cur is not None: count += 1 # cur向后移动一个节点,注意这里的cur其实已经是SingleNode对象了,有_next属性! cur = cur._next return count # 遍历链表 def travel(self): cur = self._head while cur is not None: print(cur._item) cur = cur._next print("SingleLinkList has been traveled!") # 头部添加元素 def add(self,item): # 先创建一个保存item的节点 node = SingleNode(item) # 将新节点的_next指向头结点,即指向_head指向的位置 node._next = self._head # 将链表的头_head指向新节点 self._head = node # 尾部添加元素 def append(self,item): node = SingleNode(item) # 判断链表是否为空,为空的话将_head指向新的节点 if self.is_empty: self._head = node # 若不为空,则找到尾部,将尾节点的next指向新的节点 else: cur = self._head while cur._next is not None: cur = cur._next cur._next = node # 指定位置添加元素 def insert(self,pos,item): # 若指定位置pos在第一个元素之前,则执行头部插入add方法 if pos <= 0: self.add(item) # 若指定位置pos超过链表尾部,则执行尾部插入append方法 elif pos >= self.length: self.append(item) # 找到指定位置插入元素 else: node = SingleNode(item) count = 0 # pre表示pos的前一个位置pos-1,需要先从头节点开始移动到pre这个位置 pre = self._head while count < (pos-1): count += 1 pre = pre._next # 先将新节点node的next指向插入位置的节点 node._next = pre._next # 再将“插入位置的前一个节点”的next指向新的节点 pre._next = node # 删除节点 def remove(self,item): cur = self._head pre = None while cur is not None: # 找到了指定元素 if cur._item == item: # 如果第一个节点就是需要删除的节点 if not pre: # 将头指针指向头节点后的第一个节点 self._head = cur._next else: # 将删除位置的前一个节点的next指向删除位置的后一个节点 pre._next = cur._next break # 没有找到指定的元素 else: # 继续按链表后移节点 pre = cur cur = cur._next # 查找节点是否存在 def search(self,item)->bool: cur = self._head while cur is not None: if cur._item == item: return True cur = cur._next return False if __name__ == '__main__': s = SingleLinkList() print(f"SingleLinkList is_empty? <{s.is_empty}>") s.add(11) s.add(12) s.travel() s.append(22) s.append(33) s.travel() s.insert(3,"666") s.travel() s.remove(22) s.travel() print(f"SingleLinkList is_empty? <{s.is_empty}>") print(f"Does 12 in SingleLinkList? <{s.search(12)}>") print(f"Does 22 in SingleLinkList? <{s.search(22)}>")
单向循环链表
# 节点类 class Node(object): def __init__(self,item): self._item = item self._next = None # 单向循环链表 class SinCycLinkedList(object): def __init__(self): self._head = None # 判断链表是否为空 @property def is_empty(self)->bool: return self._head is None # 求链表的长度 @property def length(self)->int: if self.is_empty: return 0 count = 1 cur = self._head # 注意循环的条件 while cur._next != self._head: count += 1 cur = cur._next return count # 遍历链表 def travel(self): if self.is_empty: return # 第一个节点单独处理 cur = self._head print(cur._item) # 注意循环的条件 while cur._next != self._head: cur = cur._next print(cur._item) print("SinCycLinkedList has been traveled!") # 头部添加节点 def add(self,item): # 实例化一个Node对象 node = Node(item) if self.is_empty: # 循环单向链表尾节点指向头节点 self._head = node node._next = self._head else: # 先将添加的节点指向_head node._next = self._head # 移动到链表的尾部,将尾部的节点的_next指向node cur = self._head while cur._next != self._head: cur = cur._next cur._next = node # _head指向新添加的node self._head = 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 cur._next = node # 将node指向头节点_head node._next = self._head # 指定位置添加节点 def insert(self,pos,item): # 首部添加 if pos <= 0: self.add(item) # 尾部添加 elif pos >= self.length: self.append(item) # 指定位置添加 else: node = Node(item) cur = self._head count = 0 # 先移动到指定位置的前一个节点,注意这里与pos-1比较! while count < (pos-1): count += 1 cur = cur._next # 先将node的下一个节点设置为cur的_next,然后再将cur的_next设置为node,注意顺序不能反! node._next = cur._next cur._next = node # 删除一个节点 def remove(self,item): # 若链表为空则直接返回None if self.is_empty: return # 先将cur指向头节点 cur = self._head pre = None # 若头节点的元素正好是要查找的元素 if cur._item == item: # 若链表不止有一个节点 if cur._next != self._head: # 先找到尾节点,将尾节点的_next指向第二个节点 while cur._next != self._head: cur = cur._next # 注意cur现在就是尾节点,并且最后需要将self._head指向第二个节点! cur._next = self._head._next self._head = self._head._next # 链表只有一个节点直接让_head指向None else: self._head = None else: pre = self._head # 注意不删除第一个节点! while cur._next != self._head: # 找到了要删除的元素 if cur._item == item: pre._next = cur._next return # 否则pre与cur往前挪动位置 pre = cur cur = cur._next # 临界情况:while循环结束还没找到的话,此时cur就是尾节点,需要单独处理 if cur._item == item: # 尾部删除,让尾节点的上一个节点pre的_next指向头节点即可 pre._next = cur._next # 查找节点是否存在 def search(self,item)->bool: # 空链表直接返回False if self.is_empty: return False cur = self._head # 如果头节点正好是要找的元素 if cur._item == item: return True # 否则遍历链表 while cur._next != self._head: # 先移动再比较! cur = cur._next if cur._item == item: return True # 遍历完后还没找到就返回False return False if __name__ == '__main__': lst = SinCycLinkedList() print(f"lst is empty? <{lst.is_empty}>") lst.add(1) lst.add(2) lst.travel() lst.append(33) lst.append(44) lst.travel() lst.insert(2,"OK") lst.travel() print(f"lst's length is {lst.length}") lst.remove(44) lst.travel() print(f"lst is empty? <{lst.is_empty}>") print(f"Does OK in lst? <{lst.search('OK')}>") print(f"Does 666 in lst? <{lst.search('666')}>")
栈
# 栈:last in first out class Stack(object): def __init__(self): self.items = [] # 是否为空 @property def is_empty(self): return self.items == [] # 添加元素——append在后面添加 def push(self,item): self.items.append(item) # 弹出元素——pop弹出最后面的元素 def pop(self): return self.items.pop() # 返回栈顶元素 @property def peek(self): return self.items[len(self.items)-1] # 返回栈的大小 @property def size(self): return len(self.items) if __name__ == '__main__': s = Stack() print(f"s is empty? <{s.is_empty}>") s.push("hello") s.push("world") s.push("whw") print(f"s is empty? <{s.is_empty}>") print(f"s's size is {s.size}") print(s.pop()) print(s.peek)
二叉树
# coding:utf-8 class Node(object): """""" def __init__(self, item): self.elem = item self.lchild = None self.rchild = None class Tree(object): """二叉树""" def __init__(self): self.root = None def add(self, item): node = Node(item) if self.root is None: self.root = node return queue = [self.root] while queue: cur_node = queue.pop(0) if cur_node.lchild is None: cur_node.lchild = node return else: queue.append(cur_node.lchild) if cur_node.rchild is None: cur_node.rchild = node return else: queue.append(cur_node.rchild) def breadth_travel(self): """广度遍历""" if self.root is None: return queue = [self.root] while queue: cur_node = queue.pop(0) print(cur_node.elem, end=" ") if cur_node.lchild is not None: queue.append(cur_node.lchild) if cur_node.rchild is not None: queue.append(cur_node.rchild) def preorder(self, node): """先序遍历""" if node is None: return print(node.elem, end=" ") self.preorder(node.lchild) self.preorder(node.rchild) def inorder(self, node): """中序遍历""" if node is None: return self.inorder(node.lchild) print(node.elem, end=" ") self.inorder(node.rchild) def postorder(self, node): """后序遍历""" if node is None: return self.postorder(node.lchild) self.postorder(node.rchild) print(node.elem, end=" ") if __name__ == "__main__": tree = Tree() tree.add(0) tree.add(1) tree.add(2) tree.add(3) tree.add(4) tree.add(5) tree.add(6) tree.add(7) tree.add(8) tree.add(9) tree.breadth_travel() print(" ") tree.preorder(tree.root) print(" ") tree.inorder(tree.root) print(" ") tree.postorder(tree.root) print(" ")
~~