java带权连通图上最小权边,连通图最小生成树的算法及实现
連通圖的最小生成樹(shù)
生成樹(shù)定義:
無(wú)向連通圖G的極小連通子圖,稱為它的生成樹(shù)。(n個(gè)頂點(diǎn),n-1條邊)
考慮一下下面這個(gè)圖
上圖是一個(gè)完全圖,它的生成樹(shù)不是唯一的,我們列出最特殊的兩種情況
上面2個(gè)圖都是第一個(gè)完全圖的生成樹(shù),但是2者是完全不同的。
按照深度優(yōu)先遍歷生成的生成樹(shù),稱為深度優(yōu)先生成樹(shù)
按照廣度優(yōu)先遍歷生成的生成樹(shù),稱為廣度優(yōu)先生成樹(shù)
非連通圖的生成森林,概念比較簡(jiǎn)單,無(wú)非就是非連通圖的極大連通子圖和生成樹(shù)的概念疊加
最小生成樹(shù)
圖G是帶權(quán)的無(wú)向連通圖,生成樹(shù)上個(gè)邊權(quán)值之和稱為生成樹(shù)的代價(jià),代價(jià)最小的生成樹(shù)稱為最小生成樹(shù)。
最小生成樹(shù)的生成算法
Prim算法
現(xiàn)有連通圖G=(V, E),其最小連通圖TG=(TV, TE)。
初始狀態(tài)下:V = {V0, V1, V2 ... Vn}; TV = {}
從V當(dāng)中任選一頂點(diǎn),插入TV,V = {V0, V1, V2 ... Vn}; TV = {V0}
找連接TV和V-TV這兩個(gè)集合的權(quán)值最小的邊,插入TE,并把該邊2頂點(diǎn)當(dāng)中原本不屬于TV的頂點(diǎn)加入TV;
重復(fù)上一步驟
知道V = TV
下面是java實(shí)現(xiàn),首先我們需要修改一下之前的生成圖的代碼,我們生成了一棵7個(gè)頂點(diǎn)的完全圖,每一條邊的權(quán)值是100以內(nèi)的隨機(jī)數(shù)。
Graph graph = new Graph();
String nodeNames[] = {"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg"};
for (String s : nodeNames) {
graph.nodes.add(new Node(s));
}
graph.arcs = new int[nodeNames.length][nodeNames.length];
Random ra = new Random();
for (int i = 0; i < graph.nodes.size(); i ++){
for (int j = 0; j < graph.nodes.size(); j ++){
if (i != j){
graph.arcs[i][j] = ra.nextInt(100) + 1;
}
}
}
然后是最小生成樹(shù)的Prim算法實(shí)現(xiàn),解釋一下,首先創(chuàng)建一個(gè)二維數(shù)組表示邊,把空間都分配好,只等著往里面填數(shù)就行。然后是一個(gè)TreeMap對(duì)象,來(lái)保存頂點(diǎn),之所以用TreeMap,是為了保證新圖的頂點(diǎn)順序和原圖是一致的。剩下的基本就是跟前面算法描述的差不多,大家對(duì)著看就行,沒(méi)什么太難的地方。
public Graph getMinTree(){
int newArcs[][] = new int[this.nodes.size()][this.nodes.size()];
Map newNodes = new TreeMap();
newNodes.put(0, this.nodes.get(0));
while(newNodes.size() != this.nodes.size()){
int minWeight = 99999;
int minI = -1;
int minJ = -1;
for(int i : newNodes.keySet()){
for (int j = 0; j < this.nodes.size(); j ++){
if (i != j && !newNodes.containsKey(j)){
if (this.arcs[i][j] < minWeight){
minWeight = this.arcs[i][j];
minI = i;
minJ = j;
}
}
}
}
newNodes.put(minJ, this.nodes.get(minJ));
newArcs[minI][minJ] = minWeight;
newArcs[minJ][minI] = minWeight;
}
Graph res = new Graph();
res.arcs = newArcs;
res.nodes.addAll(newNodes.values());
return res;
}
下面有一次測(cè)試的輸出,2個(gè)圖,分別是原圖的所有權(quán)值信息,另一個(gè)是最小生成樹(shù)的權(quán)值信息
然后還可以用連通圖的dfs算法檢查一下。
Kruskal算法
先將所有邊按照權(quán)值,從小到大排序
依次訪問(wèn)各邊,如果生成回路,則舍棄,否則加入生成樹(shù),同時(shí)將該邊的另一頂點(diǎn)加入生成樹(shù)
直到所有頂點(diǎn)被加入
java實(shí)現(xiàn),省略。
總結(jié)
以上是生活随笔為你收集整理的java带权连通图上最小权边,连通图最小生成树的算法及实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SpringMVC请求中的普通、POJO
- 下一篇: android 本地资源 uri,And