概念:在含有n個頂點的連通網中選擇n-1條邊,構成一顆極小連通子圖,並使該連通子圖中n-1條邊上的權值之和達到最小,則稱這顆連通子圖爲連通網的最小生成樹。
{
1.環境:連通網
2.選取n-1條邊
3.連通子圖
4.權值最小
}
克魯斯卡爾算法
邊按照權值遞增順序排列,循環按順序取邊,若形成環則此邊不取,修改連通分量,直到選取了n-1條邊停止循環(n爲頂點個數)
形成環的條件:起始頂點和結束頂點在同一個連通分量(子圖)中
//邊
public class Edge implements Comparable<Edge>{
int start; //起始頂點
int end; //結束頂點
int weight; //權值
public Edge(int start, int end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
//按照權值遞增排列
@Override
public int compareTo(Edge o) {
return this.weight-o.weight;
}
@Override
public String toString() {
return "Edge{" +
"start=" + start +
", end=" + end +
", weight=" + weight +
'}';
}
}
//克魯斯卡爾算法
public class Kruskal {
/**
*
* @param vertex 頂點集合
* @param list 邊代表連通網
* @return 返回最小生成子圖的邊的集合
*/
public static List<Edge> minTree(int[] vertex, List<Edge> list){
List<Edge> edges = new ArrayList<>();
//按照權值遞增排序
Collections.sort(list);
//記錄連通分量(頂點之間有邊相連)
ArrayList<ArrayList<Integer>> records = new ArrayList<>();
//記錄list的索引
int index = 0;
//遍歷邊集合 當選擇的邊數大於等於頂點個數-1停止循環
while(edges.size()<vertex.length-1){
Edge edge = list.get(index++);
//記錄起始頂點所在連通分量索引
int x1 = -1;
//記錄結束頂點所在連通分量索引
int x2 = -2;
//遍歷records判斷是否在同一個連通分量
for(int i = 0;i<records.size();i++){
ArrayList<Integer> list1 = records.get(i);
for(int j=0;j<list1.size();j++){
if(edge.start==list1.get(j)){
x1=i;
}
if(edge.end==list1.get(j)){
x2=i;
}
}
}
//如果x1!=x2說明沒有形成環,修改連通分量
if(x1!=x2){
edges.add(new Edge(edge.start,edge.end,edge.weight));
//雙頂點都不在連通分量中,新增連通分量
if(x1==-1&&x2==-2){
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(edge.start);
list1.add(edge.end);
records.add(list1);
}else if(x1==-1){
//起始頂點不在連通分量中
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(edge.start);
records.add(list1);
}else if(x2==-2){
//結束頂點不在連通分量中
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(edge.end);
records.add(list1);
}else{
//雙頂點都在連通分量中,此時要合併v1與v2所在的連通分量
records.get(x1).addAll(records.get(x2));
records.remove(x2);
}
}
}
return edges;
}
public static void main(String[] args) {
int[] vertex ={1,2,3,4,5,6};
List<Edge> list = new ArrayList<>();
list.add(new Edge(1,2,6));
list.add(new Edge(1,3,1));
list.add(new Edge(1,4,5));
list.add(new Edge(2,3,5));
list.add(new Edge(2,5,3));
list.add(new Edge(3,4,5));
list.add(new Edge(3,5,6));
list.add(new Edge(3,6,4));
list.add(new Edge(4,6,2));
list.add(new Edge(5,6,6));
List<Edge> edges1 = Kruskal.minTree(vertex, list);
System.out.println(edges1);
}
}