最小生成树

ゝ一纸荒年。 2022-02-25 14:20 362阅读 0赞

kruskal算法基本思路:先对边按权重从小到大排序,先选取权重最小的一条边,如果该边的两个节点均为不同的分量,则加入到最小生成树,否则计算下一条边,直到遍历完所有的边。

prim算法基本思路:所有节点分成两个group,一个为已经选取的selected_node(为list类型),一个为candidate_node,首先任取一个节点加入到selected_node,然后遍历头节点在selected_node,尾节点在candidate_node的边,选取符合这个条件的边里面权重最小的边,加入到最小生成树,选出的边的尾节点加入到selected_node,并从candidate_node删除。直到candidate_node中没有备选节点(这个循环条件要求所有节点都有边连接,即边数要大于等于节点数-1,循环开始前要加入这个条件判断,否则可能会有节点一直在candidate中,导致死循环)。

  1. class Graph(object):
  2. def __init__(self, maps):
  3. self.maps = maps
  4. self.nodenum = self.get_nodenum()
  5. self.edgenum = self.get_edgenum()
  6. def get_nodenum(self):
  7. return len(self.maps)
  8. def get_edgenum(self):
  9. count = 0
  10. for i in range(self.nodenum):
  11. for j in range(i):
  12. if self.maps[i][j] > 0 and self.maps[i][j] < 9999:
  13. count += 1
  14. return count
  15. def kruskal(self):
  16. res = []
  17. if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
  18. return res
  19. edge_list = []
  20. # 先对于所有的边按照权重大小进行排序
  21. for i in range(self.nodenum):
  22. for j in range(i+1,self.nodenum):
  23. if self.maps[i][j] < 9999:
  24. edge_list.append([i, j, self.maps[i][j]])#按[begin, end, weight]形式加入
  25. edge_list.sort(key=lambda a:a[2])#已经排好序的边集合
  26. # 对排序好的数组从小到大进行排序,如果没有存在,那么添加到最后的列表中
  27. # 如果已经连通了,那么不执行操作
  28. group = [[i] for i in range(self.nodenum)]
  29. for edge in edge_list:
  30. for i in range(len(group)):
  31. if edge[0] in group[i]:
  32. m = i
  33. if edge[1] in group[i]:
  34. n = i
  35. if m != n:
  36. res.append(edge)
  37. group[m] = group[m] + group[n]
  38. group[n] = []
  39. print(group)
  40. return res
  41. def prim(self):
  42. res = []
  43. if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
  44. return res
  45. res = []
  46. # 设置已经存在的结点集合和待用的结点集合
  47. # 找到已经存在的结点到待用结点集合中的所有结点的权重的最小值
  48. # 执行相应的删除和添加操作
  49. seleted_node = [0]
  50. candidate_node = [i for i in range(1, self.nodenum)]
  51. while len(candidate_node) > 0:
  52. begin, end, minweight = 0, 0, 9999
  53. for i in seleted_node:
  54. for j in candidate_node:
  55. if self.maps[i][j] < minweight:
  56. minweight = self.maps[i][j]
  57. begin = i
  58. end = j
  59. res.append([begin, end, minweight])
  60. seleted_node.append(end)
  61. candidate_node.remove(end)
  62. return res
  63. max_value = 9999
  64. row0 = [0,7,max_value,max_value,max_value,5]
  65. row1 = [7,0,9,max_value,3,max_value]
  66. row2 = [max_value,9,0,6,max_value,max_value]
  67. row3 = [max_value,max_value,6,0,8,10]
  68. row4 = [max_value,3,max_value,8,0,4]
  69. row5 = [5,max_value,max_value,10,4,0]
  70. maps = [row0, row1, row2,row3, row4, row5]
  71. graph = Graph(maps)
  72. print('邻接矩阵为\n%s'%graph.maps)
  73. print('节点数据为%d,边数为%d\n'%(graph.nodenum, graph.edgenum))
  74. print('------最小生成树kruskal算法------')
  75. print(graph.kruskal())
  76. print('------最小生成树prim算法')
  77. print(graph.prim())

初始图片:

SouthEast

文章转载,原博客地址:https://blog.csdn.net/mashijia986/article/details/79100925

发表评论

表情:
评论列表 (有 0 条评论,362人围观)

还没有评论,来说两句吧...

相关阅读

    相关 生成

    最小生成树定义: 在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即![(u, v)\\in E][u_ v_in E]),而

    相关 生成

    一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 最小生成树在n个顶点的情形下,有n-1条边。生成树是对连

    相关 生成

    有n个城市,m条道路,现在输入n到m的道路的长度,用最少的边将图连接,输出让图连接的最小值 这道题我研究了好长时间才把答案看明白,现在给大家分享一下 具体代码如下

    相关 生成

    问题提出: 要在n个城市间建立通信联络网。顶点:表示城市,权:城市间通信线路的花费代价。希望此通信网花费代价最小。 问题分析: 答案只能从生成树中找,因为要做到任何

    相关 生成

    kruskal算法基本思路:先对边按权重从小到大排序,先选取权重最小的一条边,如果该边的两个节点均为不同的分量,则加入到最小生成树,否则计算下一条边,直到遍历完所有的边。 p

    相关 生成

    最小生成树 什么是最小生成树 给定一张无向带权图G=(V,E,W),从中挑选出|V|-1条边,使得V中任意两点都有直接或者间接的路径 显然,最后得到的子