普里姆算法(Prim)与最小生成树问题

普里姆算法

@anthor:QYX

普里姆算法在找最小生成树时,将顶点分为两类,一类是在查找的过程中已经包含在树中的(假设为 A 类),剩下的是另一类(假设为 B 类)。

对于给定的连通网,起始状态全部顶点都归为 B 类。在找最小生成树时,选定任意一个顶点作为起始点,并将之从 B 类移至 A 类;然后找出 B 类中到 A 类中的顶点之间权值最小的顶点,将之从 B 类移至 A 类,如此重复,直到 B 类中没有顶点为止。所走过的顶点和边就是该连通图的最小生成树。

例如,通过普里姆算法查找图 2(a)的最小生成树的步骤为:

假如从顶点A出发,顶点 B、C、D 到顶点 A 的权值分别为 2、4、2,所以,对于顶点 A 来说,顶点 B 和顶点 D 到 A 的权值最小,假设先找到的顶点 B:

继续分析顶点 C 和 D,顶点 C 到 B 的权值为 3,到 A 的权值为 4;顶点 D 到 A 的权值为 2,到 B 的权值为无穷大(如果之间没有直接通路,设定权值为无穷大)。所以顶点 D 到 A 的权值最小:

最后,只剩下顶点 C,到 A 的权值为 4,到 B 的权值和到 D 的权值一样大,为 3。所以该连通图有两个最小生成树:

另一个例子:

package com.qyx.Tree;
import java.util.Arrays;
/**
 * prim算法最小生成树解决修路问题
 * @author Administrator
 *
 */
public class PrimAlgorithm {
    public static void main(String[] args) {
        //测试图是否创建成功
        char[] data=new char[]{‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘,‘G‘};
        int verxs=data.length;
        //邻接矩阵使用二维数组表示
        int[][] weight=new int[][]{
            //A      B      C      D      E      F      G
            {10000,5,7,10000,10000,10000,2}, //A
            {5,10000,10000,9,10000,10000,3}, //B
            {7,10000,10000,10000,8,10000,10000}, //C
            {10000,9,10000,10000,10000,4,10000}, //D
            {10000,10000,8,10000,10000,5,4}, //E
            {10000,10000,10000,4,5,10000,6}, //F
            {2,3,10000,10000,4,6,10000}, //G
        };
        MGraph mgraph=new MGraph(verxs);
        MinTree minTree=new MinTree();
        minTree.createGraph(mgraph, verxs, data, weight);
        minTree.showGraph(mgraph);
        //测试普利姆算法
        minTree.prim(mgraph, 0);
    }

}
//创建最小生成树->村庄的图
class MinTree{
    //创建图的邻接矩阵
    /**
     *
     * @param graph 图对象
     * @param verxs 图对应的顶点个数
     * @param data 图的各个顶点的值
     * @param weight 图的领结矩阵
     */
    public void createGraph(MGraph graph,int verxs,char data[],int[][] weight)
    {
        int i,j;
        for(i=0;i<verxs;i++) //定点
        {
            graph.data[i]=data[i];
            for(j=0;j<verxs;j++)
            {
                graph.weight[i][j]=weight[i][j];
            }
        }
    }
    //显示图的邻接矩阵
    public void showGraph(MGraph graph)
    {
        for(int[] link:graph.weight)
        {
            System.out.println(Arrays.toString(link));
        }
    }
    //编写prim算法,得到最小生成树
    /**
     *
     * @param graph 图
     * @param v 表示从图的第几个顶点开始生成
     */
    public void prim(MGraph graph,int v)
    {
        //标记节点是否被访问过
        boolean visited[]=new boolean[graph.verx];
        for(int i=0;i<graph.verx;i++)
        {
            visited[i]=false;
        }
        //把当前这个节点标记为已访问
        visited[v]=true;
        //h1和h2记录两个顶点的下标
        int h1=-1;
        int h2=-1;
        int minWeight=10000;//将其先初始为一个大数,后面在遍历过程中会被替换
        //确定每一次生成的子图和哪个节点距离最近
        for(int k=1;k<graph.verx;k++){
            //在n个节点下,会有n-1条边
            for(int i=0;i<graph.verx;i++) //i表示被访问过的结点
            {
                for(int j=0;j<graph.verx;j++) //j结点表示还没有访问过的结点
                {
                    if(visited[i]==true&&visited[j]==false&&graph.weight[i][j]<minWeight)
                    {
                        //替换minWeight(寻找已经访问过的结点和未访问过的结点间的权值最小的边)
                        minWeight=graph.weight[i][j];
                        h1=i;
                        h2=j;
                    }
                }
            }
            //找了一条边是最小的,将当前这个结点标记为已经访问
            System.out.println(h1+"->"+h2+"权值为"+minWeight);
            visited[h2]=true;
            //minWeight重新设置为最大值
            minWeight=10000;
        }
    }
}
class MGraph{
    int verx;//表示图的节点个数
    char[] data;//存放节点的数据
    int[][] weight;//存放边,就是我们的邻接矩阵
    public MGraph(int verx) {
        this.verx=verx;
        data=new char[verx];
        weight=new int[verx][verx];
    }
}

原文地址:https://www.cnblogs.com/qyx66/p/12506817.html

时间: 2024-10-03 06:07:02

普里姆算法(Prim)与最小生成树问题的相关文章

普里姆算法-prim

算法代码: C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 /* Prim算法生成最小生成树  */ void MiniSpanTree_Prim(MGraph MG) { int min, i, j, k; int adjvex[MAXVEX];/* 

最小生成树练习3(普里姆算法Prim)

风萧萧兮易水寒,壮士要去敲代码.本女子开学后再敲了.. poj1258 Agri-Net(最小生成树)水题. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int inf=0x3f3f3f3f; 6 const int N=101; 7 int n,m; 8 int g[N][N],low[N]; 9 void prim(int u0

最小生成树(MST)----普里姆(Prim)算法与克鲁斯卡尔(Kruskal)算法

1.概念:给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树. 2.应用:例如:要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低.这就需要找到带权的最小生成树. 3.求最小生成树的算法 3.1 普里姆(Prim)算法 方法:从指定顶点开始将它加入集合中,然后将集合内的顶点与集合外的顶点所构成的所有边中选取权值最小的一条边作为生成树

普里姆算法与修路问题

应用场景-修路问题 看一个应用场景和问题: 有胜利乡有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通 各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里 问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短? 最小生成树 修路问题本质就是就是最小生成树问题, 先介绍一下最小生成树(Minimum Cost Spanning Tree),简称MST. 给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树

ACM第四站————最小生成树(普里姆算法)

对于一个带权的无向连通图,其每个生成树所有边上的权值之和可能不同,我们把所有边上权值之和最小的生成树称为图的最小生成树. 普里姆算法是以其中某一顶点为起点,逐步寻找各个顶点上最小权值的边来构建最小生成树. 其中运用到了回溯,贪心的思想. 废话少说吧,这个其实是一个模板,直接套用就好!直接上题吧!这些东西多练就好! 一.最小生成树: 题目描述 求一个连通无向图的最小生成树的代价(图边权值为正整数). 输入 第 一行是一个整数N(1<=N<=20),表示有多少个图需要计算.以下有N个图,第i图的第

46. 蛤蟆的数据结构笔记之四十六普里姆算法

46. 蛤蟆的数据结构笔记之四十六普里姆算法 本篇名言:"手莫伸 ,伸手必被捉.党与人民在监督 ,万目睽睽难逃脱.汝言惧捉手不伸 ,他道不伸能自觉 , 其实想伸不敢伸 ,人民咫尺手自缩.-- 陈毅" 连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边.所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接起来,并且使得权值的和最小.构造连通网的最小代价生成树,即最小生成树(Minimum Cost Spanning Tree). 找连通图的最

普里姆算法介绍

普里姆(Prim)算法,和克鲁斯卡尔算法一样,是用来求加权连通图的最小生成树的算法. 基本思想 对于图G而言,V是所有顶点的集合:现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T存放G的最小生成树中的边. 从所有u?U,v?(V-U) (V-U表示出去U的所有顶点)的边中选取权值最小的边(u, v),将顶点v加入集合U中,将边(u, v)加入集合T中,如此不断重复,直到U=V为止,最小生成树构造完毕,这时集合T中包含了最小生成树中的所有边. 普里姆算法图解 以上图G4为例,

普里姆算法,克鲁斯卡尔算法,迪杰斯特拉算法,弗洛里德算法

做数据结构的课程设计顺便总结一下这四大算法,本人小白学生一枚, 如果总结的有什么错误,希望能够告知指正 普里姆算法如图所示prim 找出最短的边,再以这条边构成的整体去寻找与之相邻的边,直至连接所有顶点,生成最小生成树,时间复杂度为O(n2) 克鲁斯卡尔算法如图所示kruskal 克鲁斯卡尔算法,假设连通网N=(N,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),图中每个顶点 自成一个连通分量.在E中选择代价最小的边,若该边依附的定顶点落在T中不同的连通分量上,

数据结构(五)图---最小生成树(普里姆算法)

一:最小生成树 (一)定义 我们把构造连通网的最小代价生成树称为最小生成树 (二)什么是最小生成树? 1.是一棵树 1)无回路 2)N个顶点,一定有N-1条边 2.是生成树 1)包含全部顶点 2)N-1条边都在图中 3.边的权重和最小 (三)案例说明 在实际生活中,我们常常碰到类似这种一类问题:如果要在n个城市之间建立通信联络网, 则连通n个城市仅仅须要n-1条线路.这时.我们须要考虑这样一个问题.怎样在最节省经费前提 下建立这个通信网.换句话说,我们须要在这n个城市中找出一个包括全部城市的连通