补充图的几个算法:拓扑排序算法 、kruskal算法、prim算法和Dijkstra算法实现。
一.拓扑排序算法
拓扑排序算法适用于无环的、有入度为0的图。
再说一下该算法的一个应用场景,在实现工程代码时,各个代码文件之间存在依赖关系,所以需要进行编译顺序排序。此时就可以使用拓扑排序算法实现编译顺序确定。
方法:
找到入度为0的点,然后记入result,随后擦除该点的影响(点和边),然后继续找到入度为0的点记入result,周而复始。
代码:
为方便起见,使用了我的上一篇博客中构建的图:(python)数据结构图的描述实现+其他描述方式的转换示例。
示例的图如下:
示例图的拓扑排序应为1 2 3。
def TopologySorted(graph):
'''
拓扑排序实现
:param graph:
:return:
'''
Indegree = {
} #入度字典
ZeroIndegree = [] #入度为0的点集
result = [] #结果列表
for node in graph.nodes.values():
Indegree[node] = node.indegree
if node.indegree==0:ZeroIndegree.append(node)
#拓扑排序,添加result
while len(ZeroIndegree)!=0:
node = ZeroIndegree.pop(0) #先进先出
result.append(node)
for i_n in node.nexts:
Indegree[i_n] -= 1 #擦除对直接邻居的影响,入度-1
if Indegree[i_n]==0:ZeroIndegree.append(i_n)
return result
for i in TopologySorted(graph):
print(i.value,end=' ') #output: 1 2 3
二.kruskal算法
kruskal算法适用于无向图,用于生成最小生成树。
方法:
从边的角度出发,在不形成环的前提下依次选择最小边。
代码中实现环的判断的方法:
最开始所有点各自成独立的集合,随着对边的考虑,一条边的起点和终点集合将进行合并,最后是否形成环的判定标准就是看某个点是否在某个集合中——也就是并查集结构(做查询和合并速度为常数)。
代码:
注意,以下代码实现了一种类似并查集的结构,但是没有并查集快。代码是我按照左神和k算法思路实现的,肯定还有更加优雅的方式~~btw我还是想记录自己的代码哈哈。
假设示例图为:
示例图的最小生成树应为:
使用前面链接中的方法创建图:
#创建图
graph_test = [[1,2,5], #表示从1到2的边,权重为5
[2,1,5], #表示从2到1的边,权重为5
[2,3,7], #表示从2到3的边,权重为7
[3,2,7], #表示从3到2的边,权重为7
[1,3,4], #表示从1到3的边,权重为4
[3,1,4]] #表示从3到1的边,权重为4
graph = CreateGraph(graph_test)
K算法:
class MineDSU(object):
'''
实现并查集的功能(非并查集)
'''
def __init__(self,nodes:Node):
self.total = [] #集合列表
for node in nodes.values(): #每个点各自成独立的集合
self.total.append(set([node]))
def isSame(self,fromnode:Node,tonode:Node)->bool:
'''
判断fromnode和tonode是否是同一个集合
:param fromnode:
:param tonode:
:return: