Kruskal算法的實質是從剩下的邊中找最小的那一條,如果沒有構成迴路,則加入到數組中
package Algorithm;
import java.util.Arrays;
public class Kruskal {
private int edgeNum; //記錄邊的個數
private char[] vertexs;// 頂點數組
private int[][] matrix; //鄰接矩陣
private static final int INF = Integer.MAX_VALUE; //表示兩個頂點不能聯通
//構造器
public Kruskal(char[] vertexs,int[][]matrix) {
//初始化頂點數和邊的個數
int vlen = vertexs.length;
//初始化頂點
this.vertexs = new char[vlen];
for(int i = 0; i < vertexs.length; i++) {
this.vertexs[i] = vertexs[i];
}
//初始化
this.matrix = new int[vlen][vlen];
for(int i = 0; i < vlen; i++) {
for(int j = 0; j < vlen; j++)
this.matrix[i][j] = matrix[i][j];
}
//統計邊
for(int i = 0; i < vlen; i++) {
for(int j = i + 1; j < vlen; j++)
if(matrix[i][j]!= INF)
edgeNum++;
}
}
//獲取下標爲i的頂點對應的終點
private int getEnd(int[]ends,int i) {
while(ends[i] != 0) {
i = ends[i];
}
return i;
}
//Kruskal
public void Kruskals() {
int index = 0;//表示最後結果數組的索引
int[] ends = new int[edgeNum];//邊對應的終點
//創建結果數組,保存最後的最小生成樹
Edata[] rets = new Edata[edgeNum];
//初始一共有12條邊
Edata[] edges = getEdges();
//對邊進行排序
sortEdge(edges);
//將邊加入到數組中並判斷新加的邊是否構成迴路
for(int i = 0; i < edgeNum; i++) {
//獲取到第i條邊的起點
int p1= getPosition(edges[i].start);
int p2= getPosition(edges[i].end);
//獲取p1這個結點在已有生成樹中的終點
int m = getEnd(ends,p1);
int n = getEnd(ends,p2);
if(n != m) {
ends[m] = n; //m在最小生成樹中的終點是n
rets[index++] = edges[i];//把這條邊加入到res中
}
}
//輸出res數組
for(int i = 0; i < index; i++) {
System.out.println(rets[i]);
}
}
public void print() {
System.out.println("鄰接矩陣爲:");
for(int i = 0; i < vertexs.length; i++) {
for(int j = 0; j < vertexs.length; j++)
System.out.printf("%20d\t",matrix[i][j]);
System.out.println();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
char[] vertexs = {'A','B','C','D','E','F','G'};
int matrix[][] = {
{0,12,INF,INF,INF,16,14},
{12,0,10,INF,INF,7,INF},
{INF,10,0,3,5,6,INF},
{INF,INF,3,0,4,INF,INF},
{INF,INF,5,4,0,2,8},
{16,7,6,INF,2,0,9},
{14,INF,INF,INF,8,9,0}
};
Kruskal kruskal = new Kruskal(vertexs,matrix);
kruskal.print();
System.out.println(Arrays.toString(kruskal.getEdges()));
kruskal.Kruskals();
}
//對邊進行排序處理 冒泡
private void sortEdge(Edata[] edges) {
for(int i = 0; i < edges.length - 1; i++ ) {
for(int j = 0; j < edges.length - 1;j ++) {
if(edges[j].weight > edges[j+1].weight) {
Edata temp = edges[j];
edges[j] = edges[j+1];
edges[j+1] = temp;
}
}
}
}
private int getPosition(char ch) {
for(int i = 0; i < vertexs.length;i++)
if(vertexs[i] == ch)
return i;
return -1;
}
private Edata[] getEdges() {
//獲取邊放入Edata中
int index = 0;
Edata[] data = new Edata[edgeNum];
for(int i = 0; i < vertexs.length;i++) {
for(int j = i+1;j < vertexs.length;j++)
if(matrix[i][j]!= INF )
data[index++] = new Edata(vertexs[i],vertexs[j],matrix[i][j]);
}
return data;
}
//創建一個類Edata,表示一條邊
static class Edata{
char start; //邊的起點
char end; //邊的終點
int weight;//邊的權值
public Edata(char start,char end,char weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
public Edata(char start, char end, int weight) {
super();
this.start = start;
this.end = end;
this.weight = weight;
}
@Override
public String toString() {
return "Edata [start=" + start + ", end=" + end + ", weight=" + weight + "]";
}
}
}