title: ‘最小生成树:Prim算法实现’
date: 2019-09-03 19:32:57
tags: python,数据结构
categories: 计算机理论
Prim算法
算法原理及算法流程
原理
根据(MST性质:网络G必有一颗最小生成树),具体证明不再赘述,大概思想就是假设你现有一个图的集合G,从G中的一个顶点出发,不断的选择最短的一条连接边,扩充到已选边集N中,直至N包含了图G中的所有顶点。
构造过程举例
假设现在有这样一颗图
第一次构造
V1的邻接节点全部入队。并且由于该队列是优先级队列,会按照权重排序
队首出队,构造边,将该边加入到N集
此时N集中就有了一条边了
V3
除了N集中的结点的邻接节点入队,优先队列会按照权重进行排序
第二次构造
队首出队,构造边,将该边加入到N集
此时N集有两条边了
将V6
的除N集中已有的邻接节点入队,
第三次构造
队首出队,构造边,将该边<6,4>加入到N集
此时的N集就有三条边了
将V4
的除N集中已有的邻接节点入队,发现v4的邻接顶点都在N集中了,所以没有顶点入队
第四次构造
队首<v1,v4>
出队,构造边,将该边<v1,v4>
加入到N集,注意此时由于<v1,v4>
加入N集中会构成连通,所以跳过本次构造边。
所以,当前N集中的边还是和原来一样,如下图:
将V4
的除N集中已有的邻接节点入队,发现v4的邻接顶点都在N集中了,所以没有顶点入队
第五次构造
队首<v3,v2>
出队,构造边,将该边加入到N集中。
此时N集就有五条边了
将V2
的除N集中已有的邻接节点入队
第六次构造
队首<v2,v5>
出队,构造边,加入边到N集中。此时N集中有5条边。由于总共就6个顶点,当构成最小生成树的时候边只能是5条,你如果在加一条边就连通了,所以prim构造生成树结束
最终结果
算法实现
# prim算法,最小生成树,前提该图必须是连通网
def prim(self, start):
if not self._invalid(start):
raise GraphError("不存在" + start + "这样的顶点")
result = GraphAL({})
edgeCount = 0
pqueue = [] # 优先级队列,候选列表
# 初始化优先级队列
for node in self._graph[start]:
heapq.heappush(pqueue, (self._graph[start][node], start, node))
pass
while edgeCount < self.get_vertexNum() - 1 and not pqueue.__len__() == 0:
# 出队
pair = heapq.heappop(pqueue)
distance = pair[0]
start = pair[1]
end = pair[2]
# 判断是否有该顶点,如果没有就要加入
if start not in result._graph:
result.add_vertex(start)
if end not in result._graph:
result.add_vertex(end)
# 如果当前点与下一节点未建立边,则尝试建立边
# 方式是检查下一节点是否在result中,如果有则说明这个节点已经建立过边了,再建立边的话会可能会形成连通,因此直接舍弃该边的建立
if end not in result._graph[start]:
# 如果下一个节点如果未被其他节点连接则result._graph[end]返回false,开始构造边,
# 如果下一个节点已经被连接了,则result._graph[end]返回true,舍弃该边的建立
if not result._graph[end]:
result.add_edge(start, end, distance)
edgeCount += 1
pass
start = end
# 子节点入队
for node in self._graph[start]:
if node not in result._graph:
heapq.heappush(pqueue, (self._graph[start][node], start, node))
pass
return result
测试
与刚才流程构造的结果一致