最小生成树之普里姆算法

本文将讲解生成连通图的最小生成树中的普里姆算法。

最小生成树

图中带有权值的图就是网结构。图中从一个顶点到另一个顶点的最小成本,就是n个顶点,用n-1条边把一个连通图连接起来,并且使得权值的和最小。

由于一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边。因此,我们把构造连通网的最小代价生成树称为最小生成树。

找连通图的最小生成树,经典的有两种算法,普里姆算法和克鲁斯卡尔算法,这里介绍普里姆算法。

普里姆算法原理

我们先通俗的解释下普里姆算法的原理:先随便选择一个顶点作为初始顶点(最小生成树从哪个顶点开始计算都无所谓),再选择与之连接的顶点中边的权重最小的顶点作为下一个顶点,依次按照这个规则选择顶点,一直到所有顶点都遍历完为止。此时,由这些顶点按所选择的顺序构成的生成树即为最小生成树。

下面,我将通过图形的方式解释下普里姆算法。

这里写图片描述

以上图为例,来对普里姆进行演示(选择顶点A作为初始顶点)。

第一步,选择初始顶点A

这里写图片描述

第二步,选择与A连接的最小权值边对应的顶点B

这里写图片描述

第三步,选择与B连接的最小权值边对应的顶点E

这里写图片描述

第四步,选择与E连接的最小权值边对应的顶点G

这里写图片描述

第五步,选择与G连接的最小权值边对应的顶点F

这里写图片描述

第六步,选择与F连接的最小权值边对应的顶点D

这里写图片描述

第七步,选择与D连接的最小权值边对应的顶点C

这里写图片描述

此时,最小生成树构造就完成了,它包括的顶点依次是:A B E G F D C。

普里姆算法实现

下面,将利用Java实现普里姆算法。

package test;

/**
 * 最小生成树:普里姆算法
 */
public class MinSpanTree {
    int[][] arc;                        // 邻接矩阵
    int INFINITY = Integer.MAX_VALUE;   // 顶点个数最大值
    int MAXVEX;                         // 顶点个数

    /**
     * 普里姆算法实现最小生成树
     */
    public void prim(){
        int[] lowcost = new int[MAXVEX];// 保存相关顶点间边的权值,每次循环都要从中获取到最小权值和顶点下标
        int minWeight;                  // 最小权值
        int minVertex;                  // 最小权值顶点
        int sumWeight = 0;              // 权值总和
        //先初始化将第一行的顶点权值存放到权值数组中
        for(int i = 0;i < MAXVEX;i++){
            lowcost[i] = arc[0][i];
        }

        System.out.println("从顶点0开始查找");
        for(int i = 1;i < MAXVEX;i++){
            //每次循环都找出顶点权值的最小的权值
            minWeight = INFINITY;   // 初始化最小权值为INFINITY
            minVertex = 0;
            for(int j = 1;j < MAXVEX;j++){
                if(lowcost[j] != 0 && lowcost[j] < minWeight){
                    minWeight = lowcost[j]; // 则让当前权值成为最小值
                    minVertex = j;          // 将当前最小值的下标存入minVertex
                }
            }
            //找到目标顶点minVertex,他的权值为minweight。
            System.out.println("找到顶点:"+minVertex+" 权值为:"+minWeight);
            sumWeight += minWeight;
            // 根据找到的顶点minVertex,将这一行的所有相关联的顶点权值添加到权值数组中
            lowcost[minVertex] = 0; // 将当前顶点的权值设置为0,表示此顶点已经完成任务
            for(int j = 1;j < MAXVEX;j++){
                if(lowcost[j] != 0&& arc[minVertex][j] < lowcost[j]){
                    lowcost[j] = arc[minVertex][j]; // 将较小权值存入lowcost
                }
            }
        }
        System.out.println("最小权值总和为:"+sumWeight);
    }

    private void createGraph(int index) {
        MAXVEX = index;
        arc = new int[index][index];
        int[] a0 = { 0, 10, INFINITY, INFINITY, INFINITY, 11, INFINITY, INFINITY, INFINITY };
        int[] a1 = { 10, 0, 18, INFINITY, INFINITY, INFINITY, 16, INFINITY, 12 };
        int[] a2 = { INFINITY, INFINITY, 0, 22, INFINITY, INFINITY, INFINITY, INFINITY, 8 };
        int[] a3 = { INFINITY, INFINITY, 22, 0, 20, INFINITY, 24, 16, 21 };
        int[] a4 = { INFINITY, INFINITY, INFINITY, 20, 0, 26, INFINITY, 7, INFINITY };
        int[] a5 = { 11, INFINITY, INFINITY, INFINITY, 26, 0, 17, INFINITY, INFINITY };
        int[] a6 = { INFINITY, 16, INFINITY, 24, INFINITY, 17, 0, 19, INFINITY };
        int[] a7 = { INFINITY, INFINITY, INFINITY, 16, 7, INFINITY, 19, 0, INFINITY };
        int[] a8 = { INFINITY, 12, 8, 21, INFINITY, INFINITY, INFINITY, INFINITY, 0 };
        arc[0] = a0;
        arc[1] = a1;
        arc[2] = a2;
        arc[3] = a3;
        arc[4] = a4;
        arc[5] = a5;
        arc[6] = a6;
        arc[7] = a7;
        arc[8] = a8;
    }
    public static void main(String[] args) {
        MinSpanTree graph = new MinSpanTree();
        graph.createGraph(9);
        graph.prim();
    }
}

运行结果

这里写图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值