//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;
}
}