[算法] 普里姆算法 找最小生成树

package com.guigu.algorithm.prim;

import java.util.Arrays;

/**
*@author: guorui fu
*@versiion: 1.0
*/ 
public class PrimAlgorithm {
    public static void main(String[] args) {
        char[] data = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int verxs = data.length;
        //邻接矩阵使用二维数组描述
        int[][] weight = new int[][]{
                {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}
        };

        //创建graph对象
        MGraph graph = new MGraph(verxs);
        //创建minTree
        MinTree minTree = new MinTree();
        minTree.createGraph(graph,verxs,data,weight);
        //显示图
        minTree.showGraph(graph);

        //prim算法
        minTree.prim(graph,0);

    }


}

//创建最小生成树
class MinTree{
    //创建图的邻接矩阵
    /**
     *
     * @param graph 图对象
     * @param data  图对应的顶点个数
     * @param weight 图的邻接矩阵
     */
    public void createGraph(MGraph graph,int verxs,char data[],int[][] weight){
        int i,j;
        for (int k = 0; k < verxs; k++) {//顶点
            graph.data[k] = data[k];
            for (int l = 0; l < verxs; l++) {
                graph.weight[k][l] = weight[k][l];
            }
        }
    }

    //显示图的方法
    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){
        //标记顶点是否被访问过 开始默认0
        int[] visited = new int[graph.verxs];

        //两个顶点的下标
        int h1 = -1;
        int h2 = -1;

        int minWeight = 10000;
        visited[v] = 1;//表示已访问
        //更新已访问节点,循环n-1次,找到n个节点的n-1条边的最小权值
        //已访问过节点之间不在计算之间的权值,保证每个节点都可以连接到
        for (int i = 1; i < graph.verxs; i++) {

            //下面两个for循环可以找出整个图中权值最小的边,
            // 第一层for寻找所有已访问节点 在第二层visited[j] == 1完成控制目的
            // 第二层for每一次都是从已访问节点出发 找当前节点到邻接未访问节点的最小权值,并记录权值坐标
            //两层循环后可以找到所有当前状态所有已访问节点中邻接边最小权值
            for (int j = 0; j < graph.verxs; j++) {//j节点表示被访问过的节点
                for (int k = 0; k < graph.verxs; k++) {//k节点表示还没有访问过的节点
                    if (visited[j] == 1 && visited[k] == 0 &&
                            graph.weight[j][k] < minWeight){
                        //替换minWeight 寻找已经访问过的节点和未访问的节点见的权值最小边
                        minWeight = graph.weight[j][k];
                        h1 = j;
                        h2 = k;
                    }
                }
            }
            //找到一条边是最小的
            System.out.println("边<" + graph.data[h1] + "," + graph.data[h2] + "> 权值:" + minWeight);
            //将当前这个节点标记已经访问过
            visited[h2] = 1;
            minWeight = 10000;//重新设置
        }
    }
}

class MGraph{
    int verxs ;//图的节点个数
    char[] data;//存放节点数据
    int[][] weight;//存放边,邻接矩阵

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值