数据结构与算法--普里姆算法 最小生成树 Python详细实现普里姆算法 Python详细实现最小生成树

普里姆算法概述

  • 先看一个应用场景:
    (1)修路问题:
    在这里插入图片描述
    (2)正确的思路:
    在这里插入图片描述

最小生成树

  • 最小生成树:
    在这里插入图片描述
  • 图例解析:

在这里插入图片描述

普里姆算法

  • 介绍:
    在这里插入图片描述
  • 算法核心
    在这里插入图片描述
  • 图解:
    (1)分析:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    (2)看上图知,它成功避开了长的路径(权值大的)

Python实现普里姆算法

# 创建最小生成树:村庄图
class MinTree(object):
    # 创建图的邻接矩阵
    def create_graph(self, graph, vertex: int, data: [], weight: []):
        """
        :param graph:图对象
        :param vertex:图对应的顶点个数
        :param data:图的各个顶点的值
        :param weight:图的邻接矩阵
        """
        for i in range(vertex):  # 顶点
            graph.data[i] = data[i]
            for j in range(vertex):
                graph.weight[i][j] = weight[i][j]

    # 显示图的方法
    def show_graph(self, graph):
        for link in graph.weight:
            print(link)

    # 编写prim算法,得到最小生成树
    def prim_algorithm(self, graph, v: int):
        """
        :param graph: 图对象
        :param v: 表示从图的第几个顶点开始生成,如:"A"->0 ,'B'->1...
        :return:
        """
        # visited[]标记结点(顶点)是否被访问过
        visited = [0] * graph.vertex  # 默认都是0,表示没有访问过
        visited[v] = 1  # 把当前这个结点标记为已访问过
        # h1和h2记录两个顶点的下标
        h1 = -1
        h2 = -1
        min_weight = 10000  # 将min_weight初始成一个大数,后面再遍历过程中,会被替换
        for k in range(1, graph.vertex):  # 因为有 graph.vertex顶点,普里姆算法结束后,有graph.vertex - 1条边
            # 确定每一次生成的子图,和哪个结点的距离最近
            for i in range(graph.vertex):  # i 表示被访问过的结点
                for j in range(graph.vertex):  # j 表示还没有被访问过的结点
                    if visited[i] == 1 and visited[j] == 0 and graph.weight[i][j] < min_weight:
                        # 替换 min_weight(寻找已经被访问过的结点和未被访问过的结点
                        min_weight = graph.weight[i][j]
                        h1 = i
                        h2 = j
            # 找到一条边是最小的
            print('边 %s -> %s 权值: %d ' % (graph.data[h1], graph.data[h2], min_weight))
            # 将当前这个结点标记为已经访问
            visited[h2] = 1
            # min_weight重新设置为最大值
            min_weight = 10000


class MGraph(object):
    def __init__(self, vertex):
        self.vertex = vertex  # 表示图的结点个数
        self.data = vertex * [0]  # 存放结点数据
        self.weight = [[0 for row in range(vertex)] for col in range(vertex)]  # 存放边,就是我们的邻接矩阵


if __name__ == '__main__':
    vertex_data = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    # 为了便于测试,直接传入weight,10000表示大数,表示两个点不联通
    weights = [[10000, 5, 7, 10000, 10000, 10000, 2],
               [5, 10000, 10000, 9, 10000, 10000, 3],
               [7, 10000, 10000, 10000, 8, 10000, 10000],
               [10000, 9, 10000, 10000, 10000, 4, 10000],
               [10000, 10000, 8, 10000, 10000, 5, 4],
               [10000, 10000, 10000, 4, 5, 10000, 6],
               [2, 3, 10000, 10000, 4, 6, 10000]]
    g = MGraph(len(vertex_data))
    tree = MinTree()
    tree.create_graph(g, len(vertex_data), vertex_data, weights)
    tree.show_graph(g)
    tree.prim_algorithm(g, 0)
    # tree.prim_algorithm(g, 1) 换个出发点测试下
'''输出结果
[10000, 5, 7, 10000, 10000, 10000, 2]
[5, 10000, 10000, 9, 10000, 10000, 3]
[7, 10000, 10000, 10000, 8, 10000, 10000]
[10000, 9, 10000, 10000, 10000, 4, 10000]
[10000, 10000, 8, 10000, 10000, 5, 4]
[10000, 10000, 10000, 4, 5, 10000, 6]
[2, 3, 10000, 10000, 4, 6, 10000]
边 A -> G 权值: 2 
边 G -> B 权值: 3 
边 G -> E 权值: 4 
边 E -> F 权值: 5 
边 F -> D 权值: 4 
边 A -> C 权值: 7 
'''
发布了146 篇原创文章 · 获赞 37 · 访问量 7847

猜你喜欢

转载自blog.csdn.net/storyfull/article/details/103924716
今日推荐