networkx图论Kruskal Algorithm最小生成树,Python

x33g5p2x  于2021-11-11 转载在 Go  
字(4.4k)|赞(0)|评价(0)|浏览(607)

Kruskal Algorithm和Prim最大的差异是Kruskal Algorithm是基于权边的。Kruskal Algorithm以权边维度,不断迭代加边(最小权边)。Prim是加点(最小权边的点)的。

Kruskal Algorithm每次遍历所有边权的值,每次取最小的权边,生成树枝。不一定在算法启动前期边一定连通,可以是孤立存在的非邻接边。已经加入树的边不需要重复遍历。注意图中的边很可能存在相同的权,意味着每次检查最小权边时候,返回的是list。取出最小的权边后,当加入树时候,需要检查是否构成了环,如果构成环,则废弃这个边。

当树的边等于图所有节点数减一时候,算法收敛,结束算法。

  1. import networkx as nx
  2. import matplotlib.pyplot as plt
  3. def my_graph():
  4. # 构造一个有权边的无向图,然后找出最小生成树
  5. G = nx.Graph() # 无向图
  6. nodes = ['a', 'b', 'c', 'd', 'e', 'f']
  7. G.add_nodes_from(nodes)
  8. G.add_edges_from([('a', 'b', {'weight': 6}),
  9. ('a', 'c', {'weight': 1}),
  10. ('a', 'd', {'weight': 5}),
  11. ('b', 'c', {'weight': 5}),
  12. ('c', 'd', {'weight': 5}),
  13. ('b', 'e', {'weight': 3}),
  14. ('c', 'e', {'weight': 6}),
  15. ('e', 'f', {'weight': 6}),
  16. ('c', 'f', {'weight': 4}),
  17. ('d', 'f', {'weight': 2})])
  18. pos = nx.spring_layout(G)
  19. nx.draw(G, pos,
  20. node_color='green',
  21. node_size=500,
  22. font_size=10,
  23. font_color='black',
  24. edge_color='gray',
  25. width=1,
  26. alpha=0.5,
  27. with_labels=True)
  28. my_edge_labels = nx.get_edge_attributes(G, 'weight')
  29. nx.draw_networkx_edge_labels(G, pos, edge_labels=my_edge_labels)
  30. print('邻接', list(G.adjacency()))
  31. print('所有边', G.edges())
  32. g_edges = list(G.edges(data=True))
  33. print('所有边权', g_edges)
  34. U = []
  35. V = g_edges.copy()
  36. loop_flag = True
  37. while loop_flag:
  38. print('----------')
  39. me = find_min_edge(V.copy())
  40. for e in me:
  41. U_temp = U.copy()
  42. U_temp.append(e)
  43. G_temp = nx.Graph()
  44. G_temp.add_edges_from(U_temp)
  45. try:
  46. cycle_found = nx.find_cycle(G_temp)
  47. print('连成环了,放弃这个边', cycle_found)
  48. cycle = True
  49. except nx.exception.NetworkXNoCycle:
  50. print('构图没有形成环')
  51. cycle = False
  52. if not cycle:
  53. U.append(e)
  54. V.remove(e)
  55. number_of_edge_temp = G_temp.number_of_edges()
  56. # 如果形成的图的总边==总节点数-1,说明找到的边已经完全cover
  57. if (G.number_of_nodes() - 1) == number_of_edge_temp:
  58. print('生成最小树,算法结束')
  59. loop_flag = False
  60. break
  61. print('U=', U)
  62. print('V=', V)
  63. # 把最小生成树的边着色加粗重新描边
  64. nx.draw_networkx_edges(G, pos,
  65. edgelist=U,
  66. width=8,
  67. alpha=0.5,
  68. edge_color="r")
  69. plt.show()
  70. def find_min_edge(edges):
  71. min_edge_list = []
  72. min_edge = min(edges, key=lambda x: x[2]['weight'])
  73. weight = min_edge[2]['weight']
  74. min_edge_list.append(min_edge)
  75. edges.remove(min_edge)
  76. while True:
  77. if len(edges) == 0:
  78. break
  79. edge = min(edges, key=lambda x: x[2]['weight'])
  80. w = edge[2]['weight']
  81. if w == weight:
  82. min_edge_list.append(edge)
  83. edges.remove(edge)
  84. print('找到最小权边', min_edge_list)
  85. return min_edge_list
  86. if __name__ == '__main__':
  87. my_graph()

如图:

运行日志:

  1. 邻接 [('a', {'b': {'weight': 6}, 'c': {'weight': 1}, 'd': {'weight': 5}}), ('b', {'a': {'weight': 6}, 'c': {'weight': 5}, 'e': {'weight': 3}}), ('c', {'a': {'weight': 1}, 'b': {'weight': 5}, 'd': {'weight': 5}, 'e': {'weight': 6}, 'f': {'weight': 4}}), ('d', {'a': {'weight': 5}, 'c': {'weight': 5}, 'f': {'weight': 2}}), ('e', {'b': {'weight': 3}, 'c': {'weight': 6}, 'f': {'weight': 6}}), ('f', {'e': {'weight': 6}, 'c': {'weight': 4}, 'd': {'weight': 2}})]
  2. 所有边 [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'e'), ('c', 'd'), ('c', 'e'), ('c', 'f'), ('d', 'f'), ('e', 'f')]
  3. 所有边权 [('a', 'b', {'weight': 6}), ('a', 'c', {'weight': 1}), ('a', 'd', {'weight': 5}), ('b', 'c', {'weight': 5}), ('b', 'e', {'weight': 3}), ('c', 'd', {'weight': 5}), ('c', 'e', {'weight': 6}), ('c', 'f', {'weight': 4}), ('d', 'f', {'weight': 2}), ('e', 'f', {'weight': 6})]
  4. ----------
  5. 找到最小权边 [('a', 'c', {'weight': 1})]
  6. 构图没有形成环
  7. U= [('a', 'c', {'weight': 1})]
  8. V= [('a', 'b', {'weight': 6}), ('a', 'd', {'weight': 5}), ('b', 'c', {'weight': 5}), ('b', 'e', {'weight': 3}), ('c', 'd', {'weight': 5}), ('c', 'e', {'weight': 6}), ('c', 'f', {'weight': 4}), ('d', 'f', {'weight': 2}), ('e', 'f', {'weight': 6})]
  9. ----------
  10. 找到最小权边 [('d', 'f', {'weight': 2})]
  11. 构图没有形成环
  12. U= [('a', 'c', {'weight': 1}), ('d', 'f', {'weight': 2})]
  13. V= [('a', 'b', {'weight': 6}), ('a', 'd', {'weight': 5}), ('b', 'c', {'weight': 5}), ('b', 'e', {'weight': 3}), ('c', 'd', {'weight': 5}), ('c', 'e', {'weight': 6}), ('c', 'f', {'weight': 4}), ('e', 'f', {'weight': 6})]
  14. ----------
  15. 找到最小权边 [('b', 'e', {'weight': 3})]
  16. 构图没有形成环
  17. U= [('a', 'c', {'weight': 1}), ('d', 'f', {'weight': 2}), ('b', 'e', {'weight': 3})]
  18. V= [('a', 'b', {'weight': 6}), ('a', 'd', {'weight': 5}), ('b', 'c', {'weight': 5}), ('c', 'd', {'weight': 5}), ('c', 'e', {'weight': 6}), ('c', 'f', {'weight': 4}), ('e', 'f', {'weight': 6})]
  19. ----------
  20. 找到最小权边 [('c', 'f', {'weight': 4})]
  21. 构图没有形成环
  22. U= [('a', 'c', {'weight': 1}), ('d', 'f', {'weight': 2}), ('b', 'e', {'weight': 3}), ('c', 'f', {'weight': 4})]
  23. V= [('a', 'b', {'weight': 6}), ('a', 'd', {'weight': 5}), ('b', 'c', {'weight': 5}), ('c', 'd', {'weight': 5}), ('c', 'e', {'weight': 6}), ('e', 'f', {'weight': 6})]
  24. ----------
  25. 找到最小权边 [('a', 'd', {'weight': 5}), ('b', 'c', {'weight': 5}), ('c', 'd', {'weight': 5})]
  26. 连成环了,放弃这个边 [('a', 'c'), ('c', 'f'), ('f', 'd'), ('d', 'a')]
  27. 构图没有形成环
  28. 生成最小树,算法结束
  29. U= [('a', 'c', {'weight': 1}), ('d', 'f', {'weight': 2}), ('b', 'e', {'weight': 3}), ('c', 'f', {'weight': 4}), ('b', 'c', {'weight': 5})]
  30. V= [('a', 'b', {'weight': 6}), ('a', 'd', {'weight': 5}), ('c', 'd', {'weight': 5}), ('c', 'e', {'weight': 6}), ('e', 'f', {'weight': 6})]

相关文章

最新文章

更多