数据结构与算法学习笔记 (二) 栈 链表 队列 树 堆 图 并查集 (5)

基本功能实现——堆有两点需要了解,一是堆一般采用完全二叉树;二是堆中的每一个节点都大于其左右子节点(大顶堆),或者堆中每一个节点都小于其左右子节点(小顶堆)。

class heap(object): def __init__(self): self.data_list = [] #初始化一个空堆,使用数组来存放堆元素,节省存储 def get_parent_index(self, index): #返回父节点的下标 if index == 0 or index > len(self.data_list) - 1: return None else: return (index - 1) >> 1 def swap(self, index_a, index_b): #交换数组中的两个元素 self.data_list[index_a], self.data_list[index_b] = self.data_list[index_b], self.data_list[index_a] def insert(self, data): #先把元素放在最后,然后从后往前依次堆化 #这里以大顶堆为例,如果插入元素比父节点大,则交换,直到最后 self.data_list.append(data) index = len(self.data_list) - 1 parent = self.get_parent_index(index) #循环,直到该元素成为堆顶,或小于父节点(对于大顶堆) while parent is not None and self.data_list[parent] < self.data_list[index]: self.swap(parent, index) index = parent parent = self.get_parent_index(parent) def removeMax(self): #删除堆顶元素,然后将最后一个元素放在堆顶,再从上往下依次堆化 remove_data = self.data_list[0] self.data_list[0] = self.data_list[-1] del self.data_list[-1] #堆化 self.heapify(0) return remove_data def heapify(self, index): total_index = len(self.data_list) - 1 while True: maxvalue_index = index if 2*index + 1 <= total_index and self.data_list[2*index+1] > self.data_list[maxvalue_index]: maxvalue_index = 2*index + 1 if 2*index + 2 <= total_index and self.data_list[2*index+2] > self.data_list[maxvalue_index]: maxvalue_index = 2*index + 2 if maxvalue_index == index: break self.swap(index, maxvalue_index) index = maxvalue_index

举例,将元素 1-10 放进堆,并展示建堆情况,及删除堆顶元素情况

class heap(object): def __init__(self): self.data_list = [] #初始化一个空堆,使用数组来存放堆元素,节省存储 def get_parent_index(self, index): #返回父节点的下标 if index == 0 or index > len(self.data_list) - 1: return None else: return (index - 1) >> 1 def swap(self, index_a, index_b): #交换数组中的两个元素 self.data_list[index_a], self.data_list[index_b] = self.data_list[index_b], self.data_list[index_a] def insert(self, data): #先把元素放在最后,然后从后往前依次堆化 #这里以大顶堆为例,如果插入元素比父节点大,则交换,直到最后 self.data_list.append(data) index = len(self.data_list) - 1 parent = self.get_parent_index(index) #循环,直到该元素成为堆顶,或小于父节点(对于大顶堆) while parent is not None and self.data_list[parent] < self.data_list[index]: self.swap(parent, index) index = parent parent = self.get_parent_index(parent) def removeMax(self): #删除堆顶元素,然后将最后一个元素放在堆顶,再从上往下依次堆化 remove_data = self.data_list[0] self.data_list[0] = self.data_list[-1] del self.data_list[-1] #堆化 self.heapify(0) return remove_data def heapify(self, index): total_index = len(self.data_list) - 1 while True: maxvalue_index = index if 2*index + 1 <= total_index and self.data_list[2*index+1] > self.data_list[maxvalue_index]: maxvalue_index = 2*index + 1 if 2*index + 2 <= total_index and self.data_list[2*index+2] > self.data_list[maxvalue_index]: maxvalue_index = 2*index + 2 if maxvalue_index == index: break self.swap(index, maxvalue_index) index = maxvalue_index if __name__ == "__main__": myheap = heap() for i in range(10): myheap.insert(i+1) print(\'建堆:\', myheap.data_list) print(\'删除堆顶元素:\', [myheap.removeMax() for _ in range(10)]) #输出 建堆: [10, 9, 6, 7, 8, 2, 5, 1, 4, 3] 删除堆顶元素: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

的分类
* 无向图 图是若干个顶点(Vertices)和边(Edges)相互连接组成的。边仅由两个顶点连接,并且没有方向的图称为无向图。
* 有向图 在有向图中,边是单向的:每条边连接的两个顶点都是一个有序对,它们的邻接性是单向的。我们开发过程中碰到的很多场景都是有向图:比如任务调度的依赖关系,社交网络的任务关系等等都是天然的有向图。
图的实现——表示图通常有四种方法:数组表示法、邻接表、十字链表和邻接多重表。邻接表是图的一种链式存储结构,十字链表是有向图的另一种链式存储结构,邻接多重表是无向图的另一种链式存储结构。这里主要讲解一下邻接表的表示和实现,邻接表中有两种结点,一种是头结点,另一种是表结点,头结点中存储一个顶点的数据和指向链表中第一个结点,表结点中存储当前顶点在图中的位置和指向下一条边或弧的结点,表头结点用链式或顺序结构方式存储。
无向图的实现

#图的邻接表实现 class Graph(object) : def __init__(self): self.nodes = [] #表示图的点集 self.edge = {} #表示图的边集 def insert(self, a, b): if not(a in self.nodes): #如果a 不在图的点集里,则添加a self.nodes.append(a) self.edge[a] = list() if not(b in self.nodes): self.nodes.append(b) self.edge[b] = list() self.edge[a].append(b) #a连接b self.edge[b].append(a) #b连接a def succ(self, a): return self.edge[a] #返回与a连接的点 def show_nodes(self): return self.nodes #返回图的点集 def show_edge(self): print(self.edge) if __name__ == "__main__": graph = Graph() graph.insert(\'0\', \'1\') graph.insert(\'0\', \'2\') graph.insert(\'0\', \'3\') graph.insert(\'1\', \'3\') graph.insert(\'2\', \'3\') graph.show_edge() #输出 graph的存储形式 {\'0\': [\'1\', \'2\', \'3\'], \'1\': [\'0\', \'3\'], \'2\': [\'0\', \'3\'], \'3\': [\'0\', \'1\', \'2\']}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgwzxf.html