算法 4.3节 两种Prim算法和Kruskal算法的最小生成树

//Edge
public class Edge implements Comparable<Edge> {
    private final int v;
    private final int w;
    private final double weight;

    public Edge(int v, int w, double weight) {
        this.v = v;
        this.w = w;
        this.weight = weight;
    }

    public double weight() {
        return weight;
    }

    public int either() {
        return v;
    }

    public int other(int s) {
        if (s == v) return w;
        else if (s == w) return v;
        else throw new RuntimeException("wrong edge");
    }

    public int compareTo(Edge that) {
        if (this.weight() < that.weight) return -1;
        else if (this.weight() > that.weight) return 1;
        else     return 0;
    }

}
//加权无向图
import edu.princeton.cs.algs4.Bag;

public class EdgeWeightedGraph {
    private final int V;
    private int E;
    private Bag<Edge>[] adj;

    public EdgeWeightedGraph(int v) {
        this.V = v;
        this.E = 0;
        adj = (Bag<Edge>[]) new Bag[V];
        for (int i  =0 ;i < V;i++) {
            adj[i] = new Bag<>();
        }
    }

    public int V() {
        return V;
    }

    public int E() {
        return E;
    }

    public void addEdge(Edge e) {
        int v = e.either();
        int w = e.other(v);
        adj[w].add(e);
        adj[v].add(e);
        E++;
    }

    public Iterable<Edge> adj(int v) {
        return adj[v];
    }

    public Iterable<Edge> edges() {
        Bag<Edge> bag = new Bag<>();
        for (int v =0; v < V;v++) {
            for (Edge e : adj[v]) {
                if (e.other(v) > v) bag.add(e);
            }
        }
        return bag;
    }

}
//延时Prim算法
import edu.princeton.cs.algs4.MinPQ;
import edu.princeton.cs.algs4.Queue;

public class LazyPrimMST {
    private Queue<Edge> mst;
    private boolean[] marked;
    private MinPQ<Edge> pq;

    public LazyPrimMST(EdgeWeightedGraph G) {
        mst = new Queue<Edge>();
        marked = new boolean[G.V()];
        pq = new MinPQ<>();

        visit(G, 0);
        while (!pq.isEmpty()) {
            Edge e = pq.delMin();
            int v = e.either();
            int w = e.other(v);
            if (marked[v] && marked[w]) continue;
            mst.enqueue(e);
            if (!marked[v]) visit(G, v);
            if (!marked[w]) visit(G, w);
        }
    }

    private void visit(EdgeWeightedGraph G, int v) {
        marked[v] = true;
        for (Edge e : G.adj(v)) {
            if (!marked[e.other(v)]) {
                pq.insert(e);
            }
        }
    }

    public Iterable<Edge> edges() {
        return mst;
    }
}
//即时Prim算法
import edu.princeton.cs.algs4.Bag;
import edu.princeton.cs.algs4.IndexMinPQ;

public class PrimMST {
    private Edge[] edgeTo;
    private double[] disTo;
    private IndexMinPQ<Double> pq;
    private boolean[] marked;

    public PrimMST(EdgeWeightedGraph G) {
        pq = new IndexMinPQ<>();
        edgeTo = new Edge[G.V()];
        disTo = new double[G.V()];
        marked = new boolean[G.V()];

        for (int v =0; v< G.V();v++) {
            disTo[v] = Double.POSITIVE_INFINITY;
        }
        disTo[0] = 0;
        pq.insert(0, 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() < disTo[w]) {
                edgeTo[w] = e;
                disTo[w] = e.weight();
                pq.insert(w, disTo[w]);
            }
        }
    }

    public Iterable<Edge> edges() {
        Bag<Edge> mst = new Bag<>();
        for (int v = 1;v < edgeTo.length;v++) {
            mst.add(edgeTo[v]);
        }
        return mst;
    }
}

//Kruskal算法

import edu.princeton.cs.algs4.MinPQ;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.UF;

public class KruskalMST {
    private UF uf;
    private MinPQ<Edge> pq;
    private Queue<Edge> mst;

    public KruskalMST(EdgeWeightedGraph G) {
        uf = new UF(G.V());
        pq = new MinPQ<>();
        mst = new Queue<>();
        for (Edge e : G.edges()) pq.insert(e);

        // 在Prim算法中遍历所有点,而本算法为遍历边,点必须遍历,但是边不需要,所以多了一个限定条件
        while (!pq.isEmpty() && mst.size() < G.V() - 1) {
            Edge e = pq.delMin();
            int v = e.either();
            int w = e.other(v);
            if (uf.connected(v,w)) continue;
            mst.enqueue(e);
            uf.union(v, w);
        }

    }

    public Iterable<Edge> edges(){
        return mst;
    }
}
//Boruvka算法
import edu.princeton.cs.algs4.Bag;
import edu.princeton.cs.algs4.UF;

public class BoruvkaMST {
    private UF uf;
    private Bag<Edge> mst;

    public BoruvkaMST(EdgeWeightedGraph G) {
        uf = new UF();
        mst = new Bag<>();
        Edge[] closest = new Edge[G.V()];
        for (int t = G.V(); t> 1; t = t /2 ) {

            for (Edge e: G.edges()) {
                int v = e.either();
                int w = e.other(v);
                int i = uf.find(v);
                int j = uf.find(w);
                if (i == j) continue;;
                if (e.weight() < closest[i].weight() || closest[i] == null) closest[i] =e;
                if (e.weight() < closest[j].weight() || closest[j] == null) closest[j] =e;
            }

            for (int i = 1;i<G.V();i++) {
                if (closest[i] != null) {
                    Edge e = closest[i];
                    int v = e.either();
                    int w = e.other(v);
                    if (!uf.connected(v, w)) { //避免添加两次e
                        mst.add(e);
                        uf.union(v, w);
                    }
                }
            }
        }
    }

    public Iterable<Edge> edges() {
        return mst;
    }
}
点赞