Java實(shí)現(xiàn)Kruskal算法的示例代碼
介紹
構(gòu)造最小生成樹(shù)還有一種算法,即 Kruskal 算法:設(shè)圖 G=(V,E)是無(wú)向連通帶權(quán)圖,V={1,2,...n};設(shè)最小生成樹(shù) T=(V,TE),該樹(shù)的初始狀態(tài)只有 n 個(gè)節(jié)點(diǎn)而無(wú)邊的非連通圖T=(V,{}),Kruskal 算法將這n 個(gè)節(jié)點(diǎn)看成 n 個(gè)孤立的連通分支。它首先將所有邊都按權(quán)值從小到大排序,然后值要在 T 中選的邊數(shù)不到 n-1,就做這樣貪心選擇:在邊集 E 中選擇權(quán)值最小的邊(i,j),如果將邊(i,j)加入集合 TE 中不產(chǎn)生回路,則將邊(i,j)加入邊集 TE 中,即用邊(i,j)將這兩個(gè)分支合并成一個(gè)連通分支;否則繼續(xù)選擇下一條最短邊。把邊(i,j)從集合 E 中刪去,繼續(xù)上面的貪心選擇,直到 T 中的所有節(jié)點(diǎn)都在同一個(gè)連通分支上為止。此時(shí),選取的 n-1 條邊恰好構(gòu)成圖 G 的一棵最小生成樹(shù) T。
Kruskal 算法用一種非常聰明的方法,就是運(yùn)用集合避圈;如果所選擇加入邊的起點(diǎn)和終點(diǎn)都在 T 集合中,就可以斷定會(huì)形成回路,變的兩個(gè)節(jié)點(diǎn)不能屬于同一個(gè)集合。
算法步驟
1 初始化。將所有邊都按權(quán)值從小到大排序,將每個(gè)節(jié)點(diǎn)集合號(hào)都初始化為自身編號(hào)。
2 按排序后的順序選擇權(quán)值最小的邊(u,v)。
3 如果節(jié)點(diǎn) u 和 v 屬于兩個(gè)不同的連通分支,則將邊(u,v)加入邊集 TE 中,并將兩個(gè)連通分支合并。
4 如果選取的邊數(shù)小于 n-1,則轉(zhuǎn)向步驟2,否則算法結(jié)束。
一、構(gòu)建后的圖

二、代碼
package graph.kruskal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Kruskal {
static final int N = 100;
static int fa[] = new int[N];
static int n;
static int m;
static Edge e[] = new Edge[N * N];
static List<Edge> edgeList = new ArrayList();
static {
for (int i = 0; i < e.length; i++) {
e[i] = new Edge();
}
}
// 初始化集合號(hào)為自身
static void Init(int n) {
for (int i = 1; i <= n; i++)
fa[i] = i;
}
// 合并
static int Merge(int a, int b) {
int p = fa[a];
int q = fa[b];
if (p == q) return 0;
for (int i = 1; i <= n; i++) { // 檢查所有結(jié)點(diǎn),把集合號(hào)是 q 的改為 p
if (fa[i] == q)
fa[i] = p; // a 的集合號(hào)賦值給 b 集合號(hào)
}
return 1;
}
// 求最小生成樹(shù)
static int Kruskal(int n) {
int ans = 0;
Collections.sort(edgeList);
for (int i = 0; i < m; i++)
if (Merge(edgeList.get(i).u, edgeList.get(i).v) == 1) {
ans += edgeList.get(i).w;
n--;
if (n == 1)//n-1次合并算法結(jié)束
return ans;
}
return 0;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
Init(n);
for (int i = 1; i <= m; i++) {
e[i].u = scanner.nextInt();
e[i].v = scanner.nextInt();
e[i].w = scanner.nextInt();
edgeList.add(e[i]);
}
System.out.println("最小的花費(fèi)是:" + Kruskal(n));
}
}
class Edge implements Comparable {
int u;
int w;
int v;
@Override
public int compareTo(Object o) {
if (this.w > ((Edge) o).w) {
return 1;
} else if (this.w == ((Edge) o).w) {
return 0;
} else {
return -1;
}
}
}三、測(cè)試
綠色為輸入,白色為輸出。

到此這篇關(guān)于Java實(shí)現(xiàn)Kruskal算法的示例代碼的文章就介紹到這了,更多相關(guān)Java Kruskal算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Springboot @Autowired 無(wú)法注入問(wèn)題
WebappApplication 一定要在包的最外層,否則Spring無(wú)法對(duì)所有的類進(jìn)行托管,會(huì)造成@Autowired 無(wú)法注入。接下來(lái)給大家介紹解決Springboot @Autowired 無(wú)法注入問(wèn)題,感興趣的朋友一起看看吧2018-08-08
關(guān)于Java8中map()和flatMap()的一些事
這篇文章主要給大家介紹了關(guān)于Java8中map()和flatMap()的一些事,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java實(shí)現(xiàn)解析JSON大文件JsonReader工具詳解
這篇文章主要介紹了Java實(shí)現(xiàn)解析JSON大文件的工具JsonReader使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-01-01
深入講解java線程與synchronized關(guān)鍵字
Java 中多線程的同步依靠的是對(duì)象鎖機(jī)制,synchronized關(guān)鍵字就是利用了封裝對(duì)象鎖來(lái)實(shí)現(xiàn)對(duì)共享資源的互斥訪問(wèn)。下面這篇文章主要介紹了java線程與synchronized關(guān)鍵字的相關(guān)資料,需要的朋友可以參考下。2017-03-03
SpringCloud微服務(wù)開(kāi)發(fā)基于RocketMQ實(shí)現(xiàn)分布式事務(wù)管理詳解
分布式事務(wù)是在微服務(wù)開(kāi)發(fā)中經(jīng)常會(huì)遇到的一個(gè)問(wèn)題,之前的文章中我們已經(jīng)實(shí)現(xiàn)了利用Seata來(lái)實(shí)現(xiàn)強(qiáng)一致性事務(wù),其實(shí)還有一種廣為人知的方案就是利用消息隊(duì)列來(lái)實(shí)現(xiàn)分布式事務(wù),保證數(shù)據(jù)的最終一致性,也就是我們常說(shuō)的柔性事務(wù)2022-09-09
Java中this和super的區(qū)別及this能否調(diào)用到父類使用
這篇文章主要介紹了Java中this和super的區(qū)別及this能否調(diào)用到父類使用,this和super都是Java中常見(jiàn)的關(guān)鍵字,下文關(guān)于兩者區(qū)別介紹,需要的小伙伴可以參考一下2022-05-05

