本篇咱们会聊聊最小生成树,最小生成树和以前的无向图最大的区别是这个每一条边都是带有权重的。在聊最小生成树以前 咱们要先聊两个理念,由于最小生成树是基于这两个理念的基础上获得的相关数据结构算法。php
首先咱们先了解下切分定理。在一幅加权图中,给定任意的切分,他的横切边中权重最小者必然属于图的最小生成树。找个能够想一想下要是3个节点造成换的一个节点图, 要是不把最小的边加进去,那么必然要把另外两个节点加入图中 而剩下的两条边之和确定小于最小的边在加上随机一条边,因此能够获得这个定理。算法
第二 是咱们常见的一个贪心算法,这个你们都熟因此不细述了。 在这里的应用就是找到最小生成树的一条边,不断重复直到找到最小生成树的全部边。数据结构
而最小生成树也主要用到了这两种理念,我先找到最小的一条边,生成一副图,而后找全部节点到这副图最小的权重,而后加入这图中,直至全部节点所有加入为止,这个最小生成树就算完成了,以下图。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