zoukankan      html  css  js  c++  java
  • 普里姆算法(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];
        }
    }
  • 相关阅读:
    Freemarker-2.3.22 Demo
    Freemarker-2.3.22 Demo
    Freemarker-2.3.22 Demo
    Freemarker-2.3.22 Demo
    Oracle PLSQL Demo
    Oracle PLSQL Demo
    Oracle PLSQL Demo
    Oracle PLSQL Demo
    Oracle PLSQL Demo
    Oracle PLSQL Demo
  • 原文地址:https://www.cnblogs.com/qyx66/p/12506817.html
Copyright © 2011-2022 走看看