/**
* 8.貪心算法_最小生成樹_Kruskal(克魯斯卡爾)算法
* @author Matt
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
public class Kruskal {
/**
* 建立一個Edge邊類
* @author Matt
*/
public static class Edge implements Comparable<Edge> {
// 分别代表起始節點、終止節點、權值
int u, v, w;
// 構造器
public Edge(int u, int v, int w) {
this.u = u;
this.v = v;
this.w = w;
}
@Override
// 排序,按權值從小到大排序
public int compareTo(Edge o) {
int ow = o.w;
if (w < ow)
return -;
if (w == ow)
return ;
return ;
}
}
/**
* 克魯斯卡爾算法
* @param V 序号
* @param E 邊節點
*/
public static void Kruskal(int[] V, Edge[] E) {
Arrays.sort(E);// 将邊按照權重w升序排序
// 建立一個ArrayList容器來儲存所有邊的表集合
ArrayList<HashSet> sets = new ArrayList<HashSet>();
// 從0到6進行周遊
for (int i = ; i < V.length; i++) {
// 建立一個哈希表
HashSet set = new HashSet();
// 從1開始設定邊的序号,一共5個邊
set.add(V[i]);
// 将表添加到容器中
sets.add(set);
}
// 周遊每一條邊
for (int i = ; i < E.length; i++) {
// 取出每一個邊節點的起始位置和終止位置
int start = E[i].u, end = E[i].v;
// 有些節點之間不同,賦為負值
int counti = -, countj = -;
// 從0到6周遊容器
for (int j = ; j < sets.size(); j++) {
// 取出容器中每一個邊的表
HashSet set = sets.get(j);
// 如果存在資料,counti指派為起始節點
if (set.contains(start)) {
counti = j;
}
// 如果存在資料,countj指派為終止節點
if (set.contains(end)) {
countj = j;
}
}
// 若為負值則錯誤
if (counti < || countj < )
System.err.println("沒有在子樹中找到節點,錯誤");
// 起始節點和終止節點不為同一個
if (counti != countj) {
// 列印路徑
System.out.println(
"start = " + start +
", end = " + end +
", weight = " + E[i].w);
// 從容器中取出序号為終止節點的邊
HashSet setj = sets.get(countj);
sets.remove(countj); // 移除該邊
// 從容器中取出序号為起始節點的邊
HashSet seti = sets.get(counti);
sets.remove(counti); // 移除該邊
// 設定起始節點為終止節點(進行兩點連接配接)
seti.addAll(setj);
// 将該邊添加至容器
sets.add(seti);
}
}
}
public static void main(String[] args) {
// 初始化
int[][] tree = {
{ -, , , , -, - },
{ , -, , -, , - },
{ , , -, , , },
{ , -, , -, -, },
{ -, , , -, -, },
{ -, -, , , , - } };
// 建立V和E數組
int[] V = { , , , , , };
Edge[] E = new Edge[];
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
E[] = new Edge(, , );
Kruskal(V, E);
}
}
// 運作結果:
// start = 1, end = 3, weight = 1
// start = 4, end = 6, weight = 2
// start = 2, end = 5, weight = 3
// start = 3, end = 6, weight = 4
// start = 2, end = 3, weight = 5