最小生成樹算法詳解

最小生成樹算法詳解

    • 一、最小生成樹基礎概念
      • 1.1 生成樹與最小生成樹
      • 1.2 核心性質
      • 1.3 應用場景
    • 二、Prim 算法:從頂點出發的“生長式”構建
      • 2.1 算法原理
      • 2.2 Java 代碼實現(鄰接矩陣版)
      • 2.3 復雜度分析
    • 三、Kruskal 算法:按邊權排序的“選邊式”構建
      • 3.1 算法原理
      • 3.2 Java 代碼實現(并查集+邊排序)
      • 3.3 復雜度分析
    • 四、兩種算法的對比與選擇
    • 五、最小生成樹的應用與拓展
      • 5.1 經典應用
      • 5.2 實際問題中的優化

圖論與網絡優化中,最小生成樹(Minimum Spanning Tree,MST)是一類重要問題,它能在連接所有節點的前提下,找到總權重最小的邊集合,廣泛應用于通信網絡布線、管道鋪設、電路設計等場景(核心需求是“用最少成本連接所有節點”)。

一、最小生成樹基礎概念

1.1 生成樹與最小生成樹

  • 生成樹:對于一個有 n 個節點的連通圖,生成樹是包含所有 n 個節點且恰好有 n-1 條邊的子圖,且子圖中無環(保證連通性的同時無冗余邊)。
  • 最小生成樹:在帶權連通圖中,所有生成樹中總邊權之和最小的生成樹稱為最小生成樹。

1.2 核心性質

  • 連通性:包含原圖所有節點,任意兩點之間有且僅有一條路徑。
  • 無環性:恰好有 n-1 條邊,若再添加一條邊必形成環。
  • 最小性:總邊權之和在所有可能的生成樹中最小。

1.3 應用場景

  • 通信網絡布線:用最少的線纜連接所有城市。
  • 電路設計:在芯片中用最短的導線連接所有元件。
  • 管道鋪設:以最低成本修建管道連接所有工廠。
  • 聚類分析:通過最小生成樹的邊權劃分數據簇。

二、Prim 算法:從頂點出發的“生長式”構建

Prim 算法的核心是“從一個起點開始,逐步添加邊以連接新節點,始終保持子圖無環且總權最小”。

2.1 算法原理

  1. 初始化

    • 選擇任意節點作為起點(如節點 0),標記為“已加入生成樹”。
    • 維護一個 lowCost 數組:lowCost[i] 表示未加入生成樹的節點 i 與生成樹中節點的最小邊權(若無邊連接則為 +∞)。
  2. 迭代選擇

    • lowCost 中選擇權值最小的邊,對應節點 u 加入生成樹。
    • 更新 lowCost 數組:對所有未加入生成樹的節點 v,若邊 u-v 的權值小于 lowCost[v],則更新 lowCost[v] 為該權值(因為 u 已加入生成樹,v 到生成樹的最小邊可能變為 u-v)。
  3. 終止條件

    • 當生成樹包含所有 n 個節點(共選擇 n-1 條邊),算法結束。
      prim算法

2.2 Java 代碼實現(鄰接矩陣版)

public class PrimMST {// 鄰接矩陣:graph[i][j]表示邊i-j的權值,0表示無直接連接public int[] prim(int[][] graph) {int n = graph.length;int[] parent = new int[n]; // parent[i]記錄生成樹中i的父節點(用于還原樹)int[] lowCost = new int[n]; // 未加入節點到生成樹的最小邊權boolean[] inMST = new boolean[n]; // 標記節點是否已加入生成樹// 初始化:起點為0lowCost[0] = 0;parent[0] = -1; // 起點無父節點for (int i = 1; i < n; i++) {lowCost[i] = graph[0][i] == 0 ? Integer.MAX_VALUE : graph[0][i];parent[i] = 0;}inMST[0] = true;// 共需要加入n-1個節點for (int count = 1; count < n; count++) {// 步驟1:選擇lowCost中權值最小的未加入節點uint u = -1;int min = Integer.MAX_VALUE;for (int i = 0; i < n; i++) {if (!inMST[i] && lowCost[i] < min) {min = lowCost[i];u = i;}}if (u == -1) {// 圖不連通,無法生成MSTreturn null;}inMST[u] = true; // 加入生成樹// 步驟2:更新lowCost數組for (int v = 0; v < n; v++) {if (!inMST[v] && graph[u][v] != 0 && graph[u][v] < lowCost[v]) {lowCost[v] = graph[u][v];parent[v] = u;}}}return parent; // parent數組記錄生成樹的邊(v-parent[v])}// 測試public static void main(String[] args) {// 鄰接矩陣表示帶權圖(0表示無邊)int[][] graph = {{0, 2, 0, 6, 0},{2, 0, 3, 8, 5},{0, 3, 0, 0, 7},{6, 8, 0, 0, 9},{0, 5, 7, 9, 0}};PrimMST prim = new PrimMST();int[] parent = prim.prim(graph);if (parent != null) {System.out.println("Prim生成樹的邊(子節點-父節點):");int totalWeight = 0;for (int i = 1; i < parent.length; i++) {int weight = graph[i][parent[i]];System.out.println(i + "-" + parent[i] + "(權值:" + weight + ")");totalWeight += weight;}System.out.println("總權值:" + totalWeight); // 輸出16(2+3+5+6)} else {System.out.println("圖不連通,無法生成生成樹");}}
}

2.3 復雜度分析

  • 鄰接矩陣實現:時間復雜度為 O(n2)n 為節點數),適合稠密圖(邊數接近 n2)。
  • 鄰接表+優先隊列:優化后時間復雜度為 O(m log n)m 為邊數),適合稀疏圖。
  • 空間復雜度O(n)(存儲 lowCostparent 等數組)。

三、Kruskal 算法:按邊權排序的“選邊式”構建

Kruskal 算法的核心是“按邊權從小到大選擇邊,避免形成環,直到連接所有節點”。

3.1 算法原理

  1. 初始化

    • 將所有邊按權值從小到大排序。
    • 初始化并查集(Union-Find):每個節點各自為一個集合(用于檢測環)。
    • 維護一個邊集合,用于存儲生成樹的邊。
  2. 選邊與合并

    • 按排序后的順序遍歷邊 (u, v)
      • uv 不在同一個集合(無環),則將該邊加入生成樹,并合并 uv 所在的集合。
      • uv 在同一個集合(會形成環),則跳過該邊。
  3. 終止條件

    • 當生成樹的邊數達到 n-1(連接所有節點),算法結束。
      Kruskal算法

3.2 Java 代碼實現(并查集+邊排序)

import java.util.*;// 邊的表示(起點,終點,權值)
class Edge implements Comparable<Edge> {int u, v, weight;public Edge(int u, int v, int weight) {this.u = u;this.v = v;this.weight = weight;}@Overridepublic int compareTo(Edge other) {return Integer.compare(this.weight, other.weight); // 按權值升序排序}
}// 并查集(用于檢測環)
class UnionFind {private int[] parent;public UnionFind(int n) {parent = new int[n];for (int i = 0; i < n; i++) {parent[i] = i; // 初始化:每個節點的父節點是自己}}// 查找根節點(帶路徑壓縮)public int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]); // 路徑壓縮:縮短后續查找路徑}return parent[x];}// 合并兩個集合(按秩合并優化)public boolean union(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX == rootY) {return false; // 已在同一集合(會形成環)}parent[rootY] = rootX; // 合并return true;}
}public class KruskalMST {public List<Edge> kruskal(int n, List<Edge> edges) {List<Edge> mst = new ArrayList<>();UnionFind uf = new UnionFind(n);// 步驟1:按權值從小到大排序邊Collections.sort(edges);// 步驟2:遍歷邊,選邊并避免環for (Edge edge : edges) {if (mst.size() == n - 1) {break; // 已選夠n-1條邊,生成樹完成}int u = edge.u;int v = edge.v;if (uf.union(u, v)) { // 若u和v不在同一集合(無環)mst.add(edge);}}// 若邊數不足n-1,說明圖不連通return mst.size() == n - 1 ? mst : null;}// 測試public static void main(String[] args) {int n = 5; // 5個節點List<Edge> edges = new ArrayList<>();edges.add(new Edge(0, 1, 2));edges.add(new Edge(0, 3, 6));edges.add(new Edge(1, 2, 3));edges.add(new Edge(1, 3, 8));edges.add(new Edge(1, 4, 5));edges.add(new Edge(2, 4, 7));edges.add(new Edge(3, 4, 9));KruskalMST kruskal = new KruskalMST();List<Edge> mst = kruskal.kruskal(n, edges);if (mst != null) {System.out.println("Kruskal生成樹的邊:");int totalWeight = 0;for (Edge edge : mst) {System.out.println(edge.u + "-" + edge.v + "(權值:" + edge.weight + ")");totalWeight += edge.weight;}System.out.println("總權值:" + totalWeight); // 輸出16(2+3+5+6)} else {System.out.println("圖不連通,無法生成生成樹");}}
}

3.3 復雜度分析

  • 時間復雜度O(m log m)(主要來自邊的排序,m 為邊數),適合稀疏圖(邊數少)。
  • 空間復雜度O(n + m)(存儲邊、并查集等)。

四、兩種算法的對比與選擇

特性Prim 算法Kruskal 算法
核心思想從節點出發,生長式擴展從邊出發,選邊式構建
關鍵數據結構鄰接矩陣/優先隊列并查集+排序邊
時間復雜度稠密圖 O(n2),稀疏圖 O(m log n)O(m log m)(依賴邊排序)
適用場景稠密圖(邊多節點少)稀疏圖(邊少節點多)
優勢無需排序邊,適合節點少的圖邊排序后邏輯簡單,適合邊少的圖

五、最小生成樹的應用與拓展

5.1 經典應用

  • 次小生成樹:在最小生成樹基礎上,替換一條邊得到的總權值次小的生成樹,用于容錯設計(某條邊失效時的備用方案)。
  • 多源最小生成樹:連接多個起點的最小生成樹,適用于“多中心網絡”設計(如多個數據中心連接所有城市)。

5.2 實際問題中的優化

  • 帶限制的最小生成樹:如“最多使用 k 條某類邊”,可在選邊時添加約束。
  • 動態圖的最小生成樹:當圖中邊權或節點動態變化時,高效更新生成樹(避免重新計算)。

總結
最小生成樹是解決“低成本連接所有節點”問題的核心工具,Prim 和 Kruskal 是兩種經典實現:

  • Prim 適合稠密圖,通過“生長式”擴展節點,用 lowCost 數組跟蹤最小邊。
  • Kruskal 適合稀疏圖,通過“選邊式”添加邊,用并查集避免環。
    實際應用中,需根據圖的稠密程度選擇算法:稠密圖優先用 Prim(鄰接矩陣實現),稀疏圖優先用 Kruskal(邊排序+并查集)。掌握這兩種算法,能有效解決網絡布線、聚類分析等實際問題。

That’s all, thanks for reading~~
覺得有用就點個贊、收進收藏夾吧!關注我,獲取更多干貨~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89421.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89421.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89421.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

YOLO 目標檢測的改進方法

YOLO目標檢測的改進方法可以從模型架構、訓練策略、損失函數等多個方面入手&#xff0c;以下是一些常見的改進方法方向及參考文獻&#xff1a; 模型架構改進 骨干網絡替換&#xff1a;使用更輕量或更強大的網絡替換原始骨干網絡。輕量級網絡如MobileNetV3、ShuffleNetV2等適合…

C++ 程序 AddressSanitizer:DEADLYSIGNAL

GCC && G 操作系統&#xff1a;Ubuntu 22.04 現象&#xff1a;C程序編譯時開啟ASAN&#xff0c;運行時有幾率會出現大量AddressSanitizer:DEADLYSIGNAL 參考文章&#xff1a; https://stackoverflow.com/questions/77894856/possible-bug-in-gcc-sanitizers https://st…

【強化學習】實際部署

環境 Gymnasium 作為環境接口&#xff0c; PyBullet作為物理仿真平臺&#xff0c; Stable Baselines3 用于訓練算法。 測試框架搭建 以pybullet自帶的Cart-pole-v1為例 安裝依賴&#xff1a;確保安裝了 Gymnasium 和 SB3 ( pip install gymnasium stable-baselines3 ).初始化環…

集訓Demo4

創建數據庫創建項目基本和視頻中的一樣我給User添加了vip這個屬性&#xff0c;想實現兩個令牌通過訪問的案例&#xff0c;但遇到了問題一個令牌是密碼加用戶名的map數組這是它的獲取、驗證邏輯獲取驗證另一個令牌是Int vip這是自己寫的另一套密鑰和方法獲取但在驗證這里有問題頭…

深度優化:Java 慢查詢排查與性能調優實戰

文章目錄&#x1f680; 深度優化&#xff1a;Java 慢查詢排查與性能調優實戰&#x1f6a8;1. 事故全景&#xff1a;從告警到定位&#x1f575;??♂?1.1 事故時間線&#x1f4ca; 1.2 關鍵指標異常&#x1f6e0;? 1.3 排查工具鏈&#x1f50d; 2. 深度剖析&#xff1a;MySQL…

TF-IDF(Term Frequency - Inverse Document Frequency)

TF-IDF&#xff08;Term Frequency - Inverse Document Frequency&#xff09;是一種在信息檢索與文本挖掘中非常常用的關鍵詞提取方法&#xff0c;用于衡量一個詞在文檔集合中的重要性。它的核心思想是&#xff1a;如果一個詞在某個文檔中出現得頻繁&#xff0c;同時在其他文檔…

Chrome緊急更新,谷歌修復正遭活躍利用的關鍵零日漏洞

谷歌已針對桌面版Chrome發布重要穩定渠道更新&#xff08;版本138.0.7204.157/.158&#xff09;&#xff0c;修復了六個安全漏洞&#xff0c;其中包括一個已被實際利用的漏洞。該更新正在向Windows、Mac和Linux平臺推送&#xff0c;預計未來數日或數周內將通過自動更新完成部署…

Typecho插件開發:實現文章字數統計與閱讀時長計算功能

文章目錄 Typecho文章字數統計與閱讀時長計算功能實現指南 1. 功能背景與需求分析 2. 插件設計與實現 2.1 插件基礎結構 2.2 插件主邏輯實現 2.3 代碼解析與優化 3. 前端展示優化 3.1 CSS樣式增強 3.2 多語言支持 4. 高級功能擴展 4.1 數據庫表優化 4.2 定時批量處理歷史文章 5…

開源短鏈接工具 Sink 無需服務器 輕松部署到 Workers / Pages

本文首發于只抄博客,歡迎點擊原文鏈接了解更多內容。 前言 Sink 是一款開源免費的短鏈接生成工具,支持自定義短鏈接 Slug 以及設置到期時間,并且還可以借助 Cloudflare 的 Analytics Engine 功能分析短鏈接的統計數據。 最重要的是實現以上這些功能并不需要有自己的服務器,…

嵌入式數據結構之順序表總結

以下是為嵌入式面試準備的順序表全面優化指南&#xff0c;結合高頻考點、代碼規范與嵌入式專項優化技巧&#xff0c;助你系統掌握該知識點。 一、順序表基礎與嵌入式特點 ?本質? 用連續內存空間存儲線性表元素&#xff0c;通過下標實現O(1)隨機訪問 。 ?嵌入式優勢?&#x…

Pytorch下載Mnist手寫數據識別訓練數據集的代碼詳解

datasets.MNIST(root./data, trainFalse, downloadTrue, transformtransforms.ToTensor())1. datasets.MNIST這是torchvision.datasets模塊中的一個類&#xff0c;專門用于加載MNIST數據集。MNIST是一個著名的手寫數字識別數據集&#xff0c;包含60,000個訓練樣本和10,000個測試…

汽車免拆診斷案例 | 07款豐田Hilux啟動故障

故障現象一輛 2007 年的豐田Hilux 2.5L柴油手動擋&#xff0c;行駛里程為23萬公里。車主說車輛有很多故障&#xff0c;包括故障燈閃爍、發動機啟動后又熄火、短時間運行時發動機還會劇烈抖動異響&#xff0c;從排氣管冒出大量煙霧。故障診斷接車之后進行檢查&#xff0c;發現發…

黃老師(Exeter University)學術交流

1. 文章結構與核心貢獻聚焦 強調明確切入點和核心“亮點”貢獻&#xff0c;避免分散&#xff0c;確保至少一項最主要、富有創新的方法。在該貢獻點上進行全面充分的實驗驗證&#xff0c;包括不同模型尺寸、普適性測試&#xff0c;以應對審稿專家的質疑。建議從讀者或審稿人角度…

ArcGIS Pro+PS 實現地形渲染效果圖

先前關注了B站和小紅書博主&#xff0c;設計暴風眼&#xff0c;大神講的確實好&#xff0c;深感佩服&#xff0c;自己以前的制圖僅僅實現了制圖&#xff0c;實現了把圖放在論文里能湊合&#xff0c;而不是設計。最近抽時間學習了一下大神的合集&#xff1a;ArcGIS Pro實用技法合…

ollma dify 搭建合同審查助手

目錄 windows dify: ollma 配置 ollma下載地址&#xff1a; qwen3 模型下載 這個自動下載&#xff0c;下載后自動運行。 配置環境變量&#xff1a;修改監聽后很慢 測試命令&#xff1a; 模型配置url&#xff1a; 搭建工作流 windows dify: 下載 dify代碼&#xff1a…

解鎖 iOS 按鍵精靈輔助工具自動化新可能:iOSElement.Click 讓元素交互更簡單

在移動自動化測試與腳本開發領域&#xff0c;精準操控應用元素是核心需求。無論是自動化測試流程、批量操作處理&#xff0c;還是場景化腳本開發&#xff0c;能否可靠地點擊指定元素直接決定了自動化任務的成敗。在 iOS 自動化操作中&#xff0c;開發者常常面臨三大痛點&#x…

【機器學習】AdamW可調參數介紹及使用說明

在 AdamW 算法中調整參數對模型訓練過程和最終效果有直接且重要的影響&#xff0c;以下是各關鍵參數對性能的具體影響總結&#xff1a;AdamW 主要可調參數及其影響說明 1. 學習率 lr 影響&#xff1a; 太大&#xff08;如 0.01 ~ 0.1&#xff09;&#xff1a;訓練過程不穩&…

第一篇htmlcss詳細講解

第一章 HTML標簽介紹 第一節 HTML基本結構 <!DOCTYPE html> <html><head><title>標題</title></head><body>文檔主體</body></html> HTML 標簽是由<>包圍的關鍵詞,例:<html> HTML 標簽通常成對出現,分…

安達發|從救火到未雨綢繆:APS生產計劃排產軟件重塑制造業“危機免疫力“

在全球化競爭和市場需求多變的今天&#xff0c;制造企業面臨著前所未有的挑戰。訂單波動、供應鏈中斷、設備故障等突發情況已成為常態&#xff0c;許多企業陷入了"救火式管理"的惡性循環。據統計&#xff0c;超過70%的制造企業管理者將超過50%的工作時間用于處理各種…

短視頻矩陣系統:選擇與開發的全方位指南

短視頻矩陣系統&#xff1a;選擇與開發的全方位指南在當今數字化時代&#xff0c;短視頻已經成為企業營銷和個人品牌建設的重要工具。為了更高效地管理和發布短視頻&#xff0c;許多企業和個人開始尋求短視頻矩陣系統的解決方案。本文將深入探討短視頻矩陣系統哪家好、短視頻批…