ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【程序员必会十大算法】之Prim算法

2021-09-27 10:04:12  阅读:155  来源: 互联网

标签:10000 weight mGraph int vertexNum 程序员 算法 权值 Prim


问题

在这里插入图片描述
①胜利乡有7个村庄(A, B,C,D,E,F,G),现在需要修路把7个村庄连通
②各个村庄的距离用边线表示(权),比如A-B距离5公里
③问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?

代码

重点理解createMinTree中的三层for循环

public class Main {
    public static void main(String[] args) {
        char[] data = {'A','B','C','D','E','F','G'};
        int[][] weight = {
                {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,10006,10000,5,4},
                {10000,10000,10000,4,5,10000,6},
                {2,3,10000,10000,4,6,10000}};

        MGraph mGraph = new MGraph(data.length);
        mGraph.createGraph(data,weight);
        mGraph.showGraph();

        createMinTree(mGraph,0);
    }

    /**
     *
     * @param mGraph 表示图
     * @param startIndex 表示开始的点的下标 比如从A开始,则传0
     */
    public static void createMinTree(MGraph mGraph,int startIndex){
        if (mGraph.vertexNum == 0){
            return;
        }
        //创建是否访问数组
        boolean[] isVisited = new boolean[mGraph.vertexNum];
        //全部初始化为 未访问
        for (int i = 0;i < mGraph.vertexNum;i++){
            isVisited[i] = false;
        }
        //将开始的点 设置成 已访问
        isVisited[startIndex] = true;

        //创建遍历到的两个点的下标
        int v1 = -1;
        int v2 = -1;
        //创建两点间距离,默认不可达
        int v1Tov2 = 10000;

        //总共 遍历mGraph.vertexNum - 1 次,因为是一条边一条边遍历的,生成最小生成树的时候,边的数目==点的数目-1
        for (int k = 0;k < mGraph.vertexNum - 1;k++){

            //每一次都要遍历 已访问的节点集合 和 未访问的节点集合
            //但是这个集合我们没创建出来,所以只能通过遍历所有的点,通过isVisited进行筛选
            for (int i = 0;i < mGraph.vertexNum;i++){
                for (int j = 0;j < mGraph.vertexNum;j++){
                    //如果有一个点已经访问,另外一个点没有被访问,且两点间可达或者距离比当前记录的举例还要小
                    if (isVisited[i] && !isVisited[j] && mGraph.weight[i][j] < v1Tov2){
                        //将v1Tov2更新
                        v1Tov2 = mGraph.weight[i][j];

                        v1 = i;
                        v2 = j;
                    }
                }
            }

            //遍历一次,得到两个点,即一个边,把这个边记录下来
            System.out.println("边<"+ mGraph.data[v1] + "," + mGraph.data[v2]+"> 权值:"+ v1Tov2);

            //然后为下一次遍历做初始化操作
            isVisited[v2] = true;
            v1Tov2 = 10000;
        }
    }
}
//这是图
class MGraph{
    //节点数目
    int vertexNum;
    //节点
    char[] data;
    //边的权值
    int[][] weight;

    MGraph(int vertexNum){
        this.vertexNum = vertexNum;
        data = new char[vertexNum];
        weight = new int[vertexNum][vertexNum];
    }

    //图的创建
    public void createGraph(char[] mData,int[][] mWeight){
        if (vertexNum == 0){
            return;//节点数目为0 无法创建
        }

        for (int i = 0;i < data.length;i++){
            data[i] = mData[i];
        }

        for (int i = 0;i < mWeight.length;i++){
            for (int j = 0;j < mWeight.length;j++){
                weight[i][j] = mWeight[i][j];
            }
        }
    }

    //打印图
    public void showGraph(){
        if (vertexNum == 0){
            return;
        }

        for (int[] oneLine: weight){
            for (int oneNum: oneLine){
                System.out.print(oneNum + " ");
            }
            System.out.println();
        }
    }
}

结果

边<A,G> 权值:2
边<G,B> 权值:3
边<G,E> 权值:4
边<E,F> 权值:5
边<F,D> 权值:4
边<A,C> 权值:7

标签:10000,weight,mGraph,int,vertexNum,程序员,算法,权值,Prim
来源: https://blog.csdn.net/afdafvdaa/article/details/120502544

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有