本篇咱們會聊聊最小生成樹,最小生成樹和以前的無向圖最大的區別是這個每一條邊都是帶有權重的。在聊最小生成樹以前 咱們要先聊兩個理念,由於最小生成樹是基於這兩個理念的基礎上獲得的相關數據結構算法。算法
首先咱們先了解下切分定理。在一幅加權圖中,給定任意的切分,他的橫切邊中權重最小者必然屬於圖的最小生成樹。找個能夠想一想下要是3個節點造成換的一個節點圖, 要是不把最小的邊加進去,那麼必然要把另外兩個節點加入圖中 而剩下的兩條邊之和確定小於最小的邊在加上隨機一條邊,因此能夠獲得這個定理。markdown
第二 是咱們常見的一個貪心算法,這個你們都熟因此不細述了。 在這裏的應用就是找到最小生成樹的一條邊,不斷重複直到找到最小生成樹的全部邊。數據結構
而最小生成樹也主要用到了這兩種理念,我先找到最小的一條邊,生成一副圖,而後找全部節點到這副圖最小的權重,而後加入這圖中,直至全部節點所有加入爲止,這個最小生成樹就算完成了,以下圖。ide
如今經常使用在最小生成樹的算法代碼是prim算法code
package com.jimmysun.algorithms.chapter4_3; import com.jimmysun.algorithms.chapter1_3.Queue; import edu.princeton.cs.algs4.IndexMinPQ; public class Ex22PrimMST { private Edge[] edgeTo; private double[] distTo; private boolean[] marked; private IndexMinPQ<Double> pq; public Ex22PrimMST(EdgeWeightedGraph G) { edgeTo = new Edge[G.V()]; distTo = new double[G.V()]; marked = new boolean[G.V()]; for (int v = 0; v < G.V(); v++) { distTo[v] = Double.POSITIVE_INFINITY; } pq = new IndexMinPQ<Double>(G.V()); for (int v = 0; v < G.V(); v++) { if (!marked[v]) { distTo[v] = 0.0; pq.insert(v, 0.0); while (!pq.isEmpty()) { visit(G, pq.delMin()); } } } } private void visit(EdgeWeightedGraph G, int v) { marked[v] = true; for (Edge e : G.adj(v)) { int w = e.other(v); if (marked[w]) { continue; } if (e.weight() < distTo[w]) { edgeTo[w] = e; distTo[w] = e.weight(); if (pq.contains(w)) { pq.changeKey(w, distTo[w]); } else { pq.insert(w, distTo[w]); } } } } public Iterable<Edge> edges() { Queue<Edge> mst = new Queue<>(); for (Edge edge : edgeTo) { if (edge != null) { mst.enqueue(edge); } } return mst; } }
具體應用 :如電路,圖像分析,航空等等blog