程序员必须会的基本算法7-Kruskal算法(库拉斯卡尔算法)

Kruskal算法

首先了解这个算法是用来干嘛的
求最小生成树的算法主要是普里姆算法和克鲁斯卡尔算法,所以它和prim算法一样是用来用最小生成树的
克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法。
基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路

问题背景

某城市新增7个站点(A,B,C,D,E,F,G),现在需要修路把7个站点连通
各个站点的距离用边线表示(权),比如A–B距离12公里
如何修路保证各个站点都能连通,并且总的修建公路总里程最短?
在这里插入图片描述

解决

Kruskal算法的思路是这样的,
首先它是将所有的边按照权重从小到大进行了排序
然后从排序好的边中一条一条地选择加入到最小生成树中
第一步
选到的是E-F(2),判断有没有构成回路,因为E,F刚开始的顶点都是自己,所以没有构成回路,可以直接加入最小生成树数组中,设置E的顶点是F
第二步
选到的是C-D(3),C,D的顶点还是都是自己,直接加入,C的顶点是D
第三步
选的是D-E(4)边,D的顶点是D,E的顶点是F,直接加入,设置D的顶点是E
第四步
选择C-E,C的顶点是D,D的是E,E的是F,所以C的最终顶点是F,E的顶点也是F,构成回路,不能加入
下面的都差不多了,一直将所有的边都遍历一次,最小生成树就构建完成

代码解决

package basic;

import java.util.Arrays;

public class Kruskal
{
	//number表示边的个数
	public static int number;
	public static char[] nodes;
	public static final int INF=Integer.MAX_VALUE;
	public static int[][] weight;
	
 	public static void main(String[] args)
	{
 		weight= new int[][]{
 					/*A*//*B*//*C*//*D*//*E*//*F*//*G*/
 			/*A*/ {   0,  12, INF, INF, INF,  16,  14},
 			/*B*/ {  12,   0,  10, INF, INF,   7, INF},
 			/*C*/ { INF,  10,   0,   3,   5,   6, INF},
 			/*D*/ { INF, INF,   3,   0,   4, INF, INF},
 			/*E*/ { INF, INF,   5,   4,   0,   2,   8},
 			/*F*/ {  16,   7,   6, INF,   2,   0,   9},
 			/*G*/ {  14, INF, INF, INF,   8,   9,   0}}; 
 		nodes=new char[] {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
 		kruskal(nodes, weight);
 		
	}
 	
 	public static void InitNumber()
 	{
 		for(int x=0;x<nodes.length;x++)
 		{
 			for(int y=x+1;y<nodes.length;y++)
 			{
 				if(weight[x][y]!=INF)
 				{
 					number++;
 				}
 			}
 		}
 	}
 	public static void kruskal(char[] nodes,int[][] weight)
 	{
 		//初始化number
 		InitNumber();
 		
 		//返回结果的索引index,和保存结果的数组result
 		int index=0;
 		Edge[] result=new Edge[nodes.length-1];
 		
 		//用于保存每一个节点在最小生成树中的结尾是什么
 		int[] ends=new int[number];	
 		
 		//然后想的是获取所有的边,然后将所有的边进行排序
 		Edge[] edges = getEdges();
 		Sort(edges);
 		
 		//然后是判断每一条边看看是否是需要加入到最小生成树上面的
 		for(int x=0;x<number;x++)
 		{
 			//然后现在想判断的是这条边的两个节点的顶点是不是同一个顶点
 			int end1 = GetEnd(ends, edges[x].start);
 			int end2 = GetEnd(ends, edges[x].end);
 			if(end1!=end2)
 			{
 				ends[end1]=end2;
 				result[index++]=edges[x];
 			}
 		}
		System.out.println("最小生成树为");
		for(int i = 0; i < index; i++) {
			System.out.println(result[i]);
		}
 	}
 	public static int GetEnd(int[] ends,char node)
 	{
 		int index=-1;
 		for(int x=0;x<nodes.length;x++)
 		{
 			if(nodes[x]==node)
 			{
 				index=x;
 				break;
 			}
 		}
 		while(ends[index]!=0)
 		{
 			index=ends[index];
 		}
 		return index;
 	}
 	
 	public static void Sort(Edge[] edges)
 	{
 		System.out.println("前:"+Arrays.toString(edges));
 		for(int x=0;x<edges.length-1;x++)
 		{
 			for(int y=0;y<edges.length-1-x;y++)
 			{
 				if(edges[y].weight>edges[y+1].weight)
 				{
 					Edge temp=edges[y];
 					edges[y]=edges[y+1];
 					edges[y+1]=temp;
 				}
 			}
 		}
 		System.out.println("后:"+Arrays.toString(edges));
 	}
 	
 	public static Edge[] getEdges()
 	{
 		int index=0;
 		Edge[] edges=new Edge[number];
 		for(int x=0;x<nodes.length;x++)
 		{
 			for(int y=x+1;y<nodes.length;y++)
 			{
 				if(weight[x][y]!=INF)
 				{
 					edges[index++]=new Edge(nodes[x], nodes[y], weight[x][y]); 					
 				}
 			}
 		}
 		return edges;
 	}
}
/*
 * 类Edge表示一条边,保存了start(边的开头字母),end(边的结尾字母),weight(边的权重)
 */
class Edge
{
	char start;
	char end;
	int weight;
	public Edge(char start, char end, int weight)
	{
		this.start = start;
		this.end = end;
		this.weight = weight;
	}
	@Override
	public String toString()
	{
		return "<" + start + "," + end + ">=" + weight;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReflectMirroring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值