kruskal算法描述:
假设连通网N=(V,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{ }),图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。以此类推,直至T中所有顶点都在同一连通分量上为止。
kruskal算法描述如下:
package Kruskal;
/**
* 克鲁斯卡尔算法
* @author asus
*/
public class Kruskal {
private Edge[] edges; // 按权值从小到大排序后的边数组
private int edgeSize; // 边数
public Kruskal(int edgeSize) {
this.edgeSize = edgeSize;
edges = new Edge[edgeSize];
}
//定义边的内部类
class Edge {
private int begin;
private int end;
private int weight;
public Edge(int begin, int end, int weight) {
super();
this.begin = begin;
this.end = end;
this.weight = weight;
}
public int getBegin() {
return begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
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;
}
}
//通过邻接矩阵创建数组
public Edge[] createEdgeArray(int[][] matrix) {
int k = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = i + 1; j < matrix[i].length; j++) {
int m = matrix[i][j];
if (matrix[i][j] == Integer.MAX_VALUE)
continue;
edges[k] = new Edge(i, j, matrix[i][j]);
k++;
}
}
for (int i = 0; i < edges.length; i++) {
for (int j = i + 1; j < edges.length; j++) {
if (edges[j].weight < edges[i].weight) {
Edge e = edges[i];
edges[i] = edges[j];
edges[j] = e;
}
}
}
return edges;
}
public void miniSpanTreeKruskal() {
int m, n, sum = 0;
int[] parent = new int[edgeSize];// 用于验证是否构成回路,角标为某条边的起点,值为该边的终点
for (int i = 0; i < parent.length; i++) {
parent[i] = 0;
}
for (int i = 0; i < parent.length; i++) {
m = find(parent, edges[i].begin);// 以edges[i]边的起点为检索起点,找到其可以连接到的最终终点
n = find(parent, edges[i].end);// 以edges[i]边的终点为检索起点,找到其可以连接到的最终终点
if (m != n) {// 新加入的edges[i]边不会和已加入的边构成回路
parent[m] = n;
System.out.println("连接起点:" + edges[i].begin + ",连接终点:" + edges[i].end + ",权值为:" + edges[i].weight);
sum += edges[i].weight;
} else {
System.out.println("边" + i + "构成了回路");
}
}
System.out.println("sum:" + sum);
}
/**
* 在图中以node为搜索起点进行检索,最终返回检索到的终点。即表示,从起点node开始,不论以何种路径检索,最终会连接到终点。
*
* @param parent 用于检验是否构成回路的数组
* @param node 起始顶点,在parent中为角标
* @return 返回终点
*/
private int find(int[] parent, int node) {
while (parent[node] > 0) {// 已经添加了边
node = parent[node];// 以检索到的终点为新的起点继续检索
}
return node;
}
}
时间复杂度为O(eloge),适合于求边稀疏的网的最小生成树。