prim算法的java实现

MST(Minimum Spanning Tree,最小生成树)问题有两种通用的解法,Prim算法就是其中之一,它是从点的方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最小,此时将c点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条MST的边。


用图示和代码说明:

初始状态:


设置2个数据结构

lowcost[i]:表示以i为终点的边的最小权值,当lowcost[i]=0说明以i为终点的边的最小权值=0,也就是表示i点加入了MST

mst[i]:表示对应lowcost[i]的起点,即说明边<mst[i],i>是MST的一条边,当mst[i]=0表示起点i加入MST


我们假设V1是起始点,进行初始化(*代表无限大,即无通路):


lowcost[2]=6lowcost[3]=1lowcost[4]=5lowcost[5]=*,lowcost[6]=*

mst[2]=1mst[3]=1,mst[4]=1mst[5]=1,mst[6]=1(所有点默认起点是V1)


明显看出,以V3为终点的边的权值最小=1,所以边<mst[3],3>=1加入MST


此时,因为点V3的加入,需要更新lowcost数组和mst数组:

lowcost[2]=5lowcost[3]=0lowcost[4]=5lowcost[5]=6,lowcost[6]=4

mst[2]=3mst[3]=0,mst[4]=1mst[5]=3,mst[6]=3


明显看出,以V6为终点的边的权值最小=4,所以边<mst[6],6>=4加入MST


此时,因为点V6的加入,需要更新lowcost数组和mst数组:

lowcost[2]=5lowcost[3]=0lowcost[4]=2lowcost[5]=6lowcost[6]=0

mst[2]=3mst[3]=0,mst[4]=6mst[5]=3,mst[6]=0


明显看出,以V4为终点的边的权值最小=2,所以边<mst[4],4>=4加入MST


此时,因为点V4的加入,需要更新lowcost数组和mst数组:

lowcost[2]=5,lowcost[3]=0,lowcost[4]=0,lowcost[5]=6lowcost[6]=0

mst[2]=3,mst[3]=0,mst[4]=0mst[5]=3mst[6]=0


明显看出,以V2为终点的边的权值最小=5,所以边<mst[2],2>=5加入MST


此时,因为点V2的加入,需要更新lowcost数组和mst数组:

lowcost[2]=0,lowcost[3]=0,lowcost[4]=0,lowcost[5]=3,lowcost[6]=0

mst[2]=0,mst[3]=0,mst[4]=0mst[5]=2mst[6]=0


很明显,以V5为终点的边的权值最小=3,所以边<mst[5],5>=3加入MST

lowcost[2]=0,lowcost[3]=0lowcost[4]=0,lowcost[5]=0lowcost[6]=0

mst[2]=0,mst[3]=0mst[4]=0,mst[5]=0mst[6]=0


至此,MST构建成功,如图所示:

package suanfa;

public class Main {
	public static void main(String[] args) throws Exception {
		int MAX = Integer.MAX_VALUE;
		int[][] map = new int[][]{
            {0,10,MAX,MAX,MAX,11,MAX,MAX,MAX},
            {10,0,18,MAX,MAX,MAX,16,MAX,12},
            {MAX,MAX,0,22,MAX,MAX,MAX,MAX,8},
            {MAX,MAX,22,0,20,MAX,MAX,16,21},
            {MAX,MAX,MAX,20,0,26,MAX,7,MAX},
            {11,MAX,MAX,MAX,26,0,17,MAX,MAX},
            {MAX,16,MAX,MAX,MAX,17,0,19,MAX},
            {MAX,MAX,MAX,16,7,MAX,19,0,MAX},
            {MAX,12,8,21,MAX,MAX,MAX,MAX,0}
		};
		int sum = prim(map);
		System.out.println(sum);
	}
	public static int prim(int[][] arr){
		//统计最小的权
		int sum = 0;
		//当前最小生成树所能到达的顶点的最小权数组
		int[] costs = new int[9];
		//当前各个顶点对应的起点
		int[] startPoint = new int[9];
		//初始化
		for(int i =1;i<9;i++){
			//所有点的起点赋值为0
			startPoint[i] = 0;
			//以0为起点到达各个顶点的权值
			costs[i] = arr[0][i];
		}
		//挑选剩余的8个顶点
		for(int i = 1;i<9;i++){
			//记录当前costs里面的最小权值是多少
			int min = Integer.MAX_VALUE;
			//记录当前costs里面的最小权值对应的数组下标,即顶点
			//(数组[顶点]=该顶点对应的起点)
			int minIndex = 0;
			//遍历costs
			for(int j=1;j<9;j++){
				int temp = costs[j];
				//costs[j]==0代表节点j已加入MST
				if(temp!=0&&temp < min){
					min = temp;
					minIndex = j;
				}
			}
			sum+=min;
			//将已加入MST的对应的权值赋值为0
			costs[minIndex] = 0;
			//选定了新的顶点到MST后,树到达各顶点的最小开销和起点将更新
			//更新costs和startPoint
			for(int k=0;k<9;k++){
				//用minIndex顶点到各个顶点的权值比较costs数组的值,若较小则替换,并更新起点为minIndex
				int newCost = arr[minIndex][k];
				if(newCost!=0&&newCost<costs[k]){
					costs[k] = newCost;
					//更新K的起点为minIndex
					startPoint[k] = minIndex;
				}
			}
		}
		return sum;
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值