概述
克鲁斯卡尔算法:寻找图中最小生成树.
用于工程布线等
思路
拿到一张图,由边的权重从小到大,依次连接,不能有回路.连完后形成的图就是最小生成树.
首先找图中权重最小的边,把df连接起来
再连接be,再连接dg,再连接ab和ed.然后连dc,这时会形成回路,所以不连dc,照这种方法,直到所有连完最大的边.得到最小生成树.
- 连接时,如何判断是否形成回路:
只需要得到连接之前的两个顶点在各自的连通图中的最大顶点是否相同
如:要连接e和d,他们所在的连通图abe和cdf的最大顶点分别是e和f,不相同,可以连
如:要连接c和d,他们都是连通图cgdf的顶点,得到的最大顶点都是f,相同,连接后会形成回路.
步骤
- 首先定义一个边类,有起点,终点,权重
- 根据二维数组获取图中的边,按照权重排序
- 创建一个边数组,用来保存已经连起来的结果边
- 创建一个数组用来表示联通分量,数组下标表示起点,值表示终点
- 遍历排好序的边数组,获取边,得到边的起点和终点,看他们的最大顶点是否相同,不相同就连起来.更新结果数组和连通分量数组
代码:
public class Kruskal {
public int verticeSize;// 顶点数
public int[] vertices; // 顶点数组
public int[][] matrix; // 图
public int edgeSize;//边数
public static final int MAX_WEIGHT = 0xFFF8;//最大值
public Edge[] edges;//边数组
public Kruskal(int verticeSize) {
this.verticeSize = verticeSize;
matrix = new int[verticeSize][verticeSize];
}
public static class Edge{
int start;
int end;
int weight;
public Edge(int start, int end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
/**
* �获取所有的边�
* @return
*/
private Edge[] getEdges() {
int index = 0;
Edge[] edges = new Edge[verticeSize * verticeSize];
for(int i = 0;i < verticeSize; i++) {
for(int j = 0; j < verticeSize;j++) {
if (matrix[i][j] != 0 && matrix[i][j] != MAX_WEIGHT) {
edges[index++] = new Edge(i, j, matrix[i][j]);
}
}
}
edgeSize = index;
return edges;
}
private void sortEdge(Edge[] cur_edge, int size) {
for(int i = 0; i < size; i++) {
for (int j = i+1; j < size; j++) {
if (edges[i].weight > edges[j].weight) {
Edge tmp = edges[i];
edges[i] = edges[j];
edges[j] = tmp;
}
}
}
}
/**
* 核心算法
*/
public void kruskal(){
edges=getEdges();
int index=0;
Edge[] cur_edge=edges;//存放排序后的边数组
Edge[] rets=new Edge[edgeSize];//用来存放结果
sortEdge(cur_edge,edgeSize);
//定义一个数组,用来存放连通分量,用来表示连通关系的
//下标用来表示起点,值表示终点
int[] edge_temp=new int[edgeSize];
for(int i=0;in){
int temp=n;
n=m;m=temp;
}
edge_temp[m]=n;
}
}
int lengh = 0;
for(int i = 0; i < index; i++) {
lengh+= rets[i].weight;
}
System.out.println("最小生成树的权重之和" + lengh);
char[] chars = new char[verticeSize];
chars[0] = 'A';
chars[1] = 'B';
chars[2] = 'C';
chars[3] = 'D';
chars[4] = 'E';
chars[5] = 'F';
chars[6] = 'G';
for (int i = 0; i < index; i++) {
System.out.printf("(%s, %s)---> %d \n",chars[rets[i].start], chars[rets[i].end], matrix[rets[i].start][rets[i].end]);
}
}
private int getEnd(int[] edge_temp, int p) {
int i=p;
while(edge_temp[i]!=0){
i=edge_temp[i];
}
return i;
}
}
@Test
public void test(){
Kruskal graph = new Kruskal(7);
int[] v0 = new int[] {0, 50, 60, MAX_WEIGHT, MAX_WEIGHT,MAX_WEIGHT,MAX_WEIGHT};
int[] v1 = new int[] {50, 0, MAX_WEIGHT, 65, 40,MAX_WEIGHT,MAX_WEIGHT};
int[] v2 = new int[] {60, MAX_WEIGHT, 0, 52, MAX_WEIGHT,MAX_WEIGHT,45};
int[] v3 = new int[] {MAX_WEIGHT, 65, 52, 0, 50,30,42};
int[] v4 = new int[] {MAX_WEIGHT, 40, MAX_WEIGHT, 50, 0,70,MAX_WEIGHT};
int[] v5 = new int[] {MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 30,70,0,MAX_WEIGHT};
int[] v6 = new int[] {MAX_WEIGHT, MAX_WEIGHT, 45, 42,MAX_WEIGHT,MAX_WEIGHT,0};
graph.matrix[0] = v0;
graph.matrix[1] = v1;
graph.matrix[2] = v2;
graph.matrix[3] = v3;
graph.matrix[4] = v4;
graph.matrix[5] = v5;
graph.matrix[6] = v6;
graph.kruskal();
}