Question: Provide an implementation of edges() for PrimMST.java .

Answer:
/******************************************************************************
 *  Compilation:  javac PrimMST.java
 *  Execution:    java PrimMST filename.txt
 *  Dependencies: EdgeWeightedGraph.java Edge.java Queue.java
 *                IndexMinPQ.java UF.java In.java StdOut.java
 *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt
 *
 *  Compute a minimum spanning forest using Prim's algorithm.
 *
 *  %  java PrimMST tinyEWG.txt
 *  1-7 0.19000
 *  0-2 0.26000
 *  2-3 0.17000
 *  4-5 0.35000
 *  5-7 0.28000
 *  6-2 0.40000
 *  0-7 0.16000
 *  1.81000
 *
 *  % java PrimMST mediumEWG.txt
 *  1-72   0.06506
 *  2-86   0.05980
 *  3-67   0.09725
 *  4-55   0.06425
 *  5-102  0.03834
 *  6-129  0.05363
 *  7-157  0.00516
 *  ...
 *  10.46351
 *
 *  % java PrimMST largeEWG.txt
 *  ...
 *  647.66307
 *
 ******************************************************************************/

/**
 *  The {@code PrimMST} class represents a data type for computing a
 *  minimum spanning tree in an edge-weighted graph.
 *  The edge weights can be positive, zero, or negative and need not
 *  be distinct. If the graph is not connected, it computes a minimum
 *  spanning forest, which is the union of minimum spanning trees
 *  in each connected component. The {@code weight()} method returns the
 *  weight of a minimum spanning tree and the {@code edges()} method
 *  returns its edges.
 *

 *  This implementation uses Prim's algorithm with an indexed
 *  binary heap.
 *  The constructor takes Θ(E log V) time in
 *  the worst case, where V is the number of
 *  vertices and E is the number of edges.
 *  Each instance method takes Θ(1) time.
 *  It uses Θ(V) extra space (not including the
 *  edge-weighted graph).
 *

 *  This {@code weight()} method correctly computes the weight of the MST
 *  if all arithmetic performed is without floating-point rounding error
 *  or arithmetic overflow.
 *  This is the case if all edge weights are non-negative integers
 *  and the weight of the MST does not exceed 252.
 *

 *  For additional documentation,
 *  see Section 4.3 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *  For alternate implementations, see {@link LazyPrimMST}, {@link KruskalMST},
 *  and {@link BoruvkaMST}.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class PrimMST {
    private static final double FLOATING_POINT_EPSILON = 1.0E-12;

    private Edge[] edgeTo;        // edgeTo[v] = shortest edge from tree vertex to non-tree vertex
    private double[] distTo;      // distTo[v] = weight of shortest such edge
    private boolean[] marked;     // marked[v] = true if v on tree, false otherwise
    private IndexMinPQ<Double> pq;

    /**
     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.
     * @param graph the edge-weighted graph
     */
    public PrimMST(EdgeWeightedGraph graph) {
        edgeTo = new Edge[graph.V()];
        distTo = new double[graph.V()];
        marked = new boolean[graph.V()];
        pq = new IndexMinPQ<Double>(graph.V());
        for (int v = 0; v < graph.V(); v++)
            distTo[v] = Double.POSITIVE_INFINITY;

        for (int v = 0; v < graph.V(); v++)      // run from each vertex to find
            if (!marked[v]) prim(graph, v);      // minimum spanning forest

        // check optimality conditions
        assert check(graph);
    }

    // run Prim's algorithm in graph, starting from vertex s
    private void prim(EdgeWeightedGraph graph, int s) {
        distTo[s] = 0.0;
        pq.insert(s, distTo[s]);
        while (!pq.isEmpty()) {
            int v = pq.delMin();
            scan(graph, v);
        }
    }

    // scan vertex v
    private void scan(EdgeWeightedGraph graph, int v) {
        marked[v] = true;
        for (Edge e : graph.adj(v)) {
            int w = e.other(v);
            if (marked[w]) continue;         // v-w is obsolete edge
            if (e.weight() < distTo[w]) {
                distTo[w] = e.weight();
                edgeTo[w] = e;
                if (pq.contains(w)) pq.decreaseKey(w, distTo[w]);
                else                pq.insert(w, distTo[w]);
            }
        }
    }

    /**
     * Returns the edges in a minimum spanning tree (or forest).
     * @return the edges in a minimum spanning tree (or forest) as
     *    an iterable of edges
     */
    public Iterable<Edge> edges() {
        Queue<Edge> mst = new Queue<Edge>();
        for (int v = 0; v < edgeTo.length; v++) {
            Edge e = edgeTo[v];
            if (e != null) {
                mst.enqueue(e);
            }
        }
        return mst;
    }

    /**
     * Returns the sum of the edge weights in a minimum spanning tree (or forest).
     * @return the sum of the edge weights in a minimum spanning tree (or forest)
     */
    public double weight() {
        double weight = 0.0;
        for (Edge e : edges())
            weight += e.weight();
        return weight;
    }

    // check optimality conditions (takes time proportional to E V lg* V)
    private boolean check(EdgeWeightedGraph graph) {

        // check weight
        double totalWeight = 0.0;
        for (Edge e : edges()) {
            totalWeight += e.weight();
        }
        if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {
            System.err.printf("Weight of edges does not equal weight(): %f vs. %f", totalWeight, weight());
            return false;
        }

        // check that it is acyclic
        UF uf = new UF(graph.V());
        for (Edge e : edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) == uf.find(w)) {
                System.err.println("Not a forest");
                return false;
            }
            uf.union(v, w);
        }

        // check that it is a spanning forest
        for (Edge e : graph.edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) != uf.find(w)) {
                System.err.println("Not a spanning forest");
                return false;
            }
        }

        // check that it is a minimal spanning forest (cut optimality conditions)
        for (Edge e : edges()) {

            // all edges in MST except e
            uf = new UF(graph.V());
            for (Edge f : edges()) {
                int x = f.either(), y = f.other(x);
                if (f != e) uf.union(x, y);
            }

            // check that e is min weight edge in crossing cut
            for (Edge f : graph.edges()) {
                int x = f.either(), y = f.other(x);
                if (uf.find(x) != uf.find(y)) {
                    if (f.weight() < e.weight()) {
                        System.err.println("Edge " + f + " violates cut optimality conditions");
                        return false;
                    }
                }
            }

        }

        return true;
    }

    /**
     * Unit tests the {@code PrimMST} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        In in = new In(args[0]);
        EdgeWeightedGraph graph = new EdgeWeightedGraph(in);
        PrimMST mst = new PrimMST(graph);
        for (Edge e : mst.edges()) {
            StdOut.println(e);
        }
        StdOut.printf("%.5f", mst.weight());
    }

}


Question: Minimum spanning forest. Develop versions of Prim's algorithms that compute the minimum spanning forest of an edge-weighted graph that is not necessarily connected.

Answer:
/******************************************************************************
 *  Compilation:  javac PrimMST.java
 *  Execution:    java PrimMST filename.txt
 *  Dependencies: EdgeWeightedGraph.java Edge.java Queue.java
 *                IndexMinPQ.java UF.java In.java StdOut.java
 *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt
 *
 *  Compute a minimum spanning forest using Prim's algorithm.
 *
 *  %  java PrimMST tinyEWG.txt
 *  1-7 0.19000
 *  0-2 0.26000
 *  2-3 0.17000
 *  4-5 0.35000
 *  5-7 0.28000
 *  6-2 0.40000
 *  0-7 0.16000
 *  1.81000
 *
 *  % java PrimMST mediumEWG.txt
 *  1-72   0.06506
 *  2-86   0.05980
 *  3-67   0.09725
 *  4-55   0.06425
 *  5-102  0.03834
 *  6-129  0.05363
 *  7-157  0.00516
 *  ...
 *  10.46351
 *
 *  % java PrimMST largeEWG.txt
 *  ...
 *  647.66307
 *
 ******************************************************************************/

/**
 *  The {@code PrimMST} class represents a data type for computing a
 *  minimum spanning tree in an edge-weighted graph.
 *  The edge weights can be positive, zero, or negative and need not
 *  be distinct. If the graph is not connected, it computes a minimum
 *  spanning forest, which is the union of minimum spanning trees
 *  in each connected component. The {@code weight()} method returns the
 *  weight of a minimum spanning tree and the {@code edges()} method
 *  returns its edges.
 *

 *  This implementation uses Prim's algorithm with an indexed
 *  binary heap.
 *  The constructor takes Θ(E log V) time in
 *  the worst case, where V is the number of
 *  vertices and E is the number of edges.
 *  Each instance method takes Θ(1) time.
 *  It uses Θ(V) extra space (not including the
 *  edge-weighted graph).
 *

 *  This {@code weight()} method correctly computes the weight of the MST
 *  if all arithmetic performed is without floating-point rounding error
 *  or arithmetic overflow.
 *  This is the case if all edge weights are non-negative integers
 *  and the weight of the MST does not exceed 252.
 *

 *  For additional documentation,
 *  see Section 4.3 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *  For alternate implementations, see {@link LazyPrimMST}, {@link KruskalMST},
 *  and {@link BoruvkaMST}.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class PrimMST {
    private static final double FLOATING_POINT_EPSILON = 1.0E-12;

    private Edge[] edgeTo;        // edgeTo[v] = shortest edge from tree vertex to non-tree vertex
    private double[] distTo;      // distTo[v] = weight of shortest such edge
    private boolean[] marked;     // marked[v] = true if v on tree, false otherwise
    private IndexMinPQ<Double> pq;

    /**
     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.
     * @param graph the edge-weighted graph
     */
    public PrimMST(EdgeWeightedGraph graph) {
        edgeTo = new Edge[graph.V()];
        distTo = new double[graph.V()];
        marked = new boolean[graph.V()];
        pq = new IndexMinPQ<Double>(graph.V());
        for (int v = 0; v < graph.V(); v++)
            distTo[v] = Double.POSITIVE_INFINITY;

        for (int v = 0; v < graph.V(); v++)      // run from each vertex to find
            if (!marked[v]) prim(graph, v);      // minimum spanning forest

        // check optimality conditions
        assert check(graph);
    }

    // run Prim's algorithm in graph, starting from vertex s
    private void prim(EdgeWeightedGraph graph, int s) {
        distTo[s] = 0.0;
        pq.insert(s, distTo[s]);
        while (!pq.isEmpty()) {
            int v = pq.delMin();
            scan(graph, v);
        }
    }

    // scan vertex v
    private void scan(EdgeWeightedGraph graph, int v) {
        marked[v] = true;
        for (Edge e : graph.adj(v)) {
            int w = e.other(v);
            if (marked[w]) continue;         // v-w is obsolete edge
            if (e.weight() < distTo[w]) {
                distTo[w] = e.weight();
                edgeTo[w] = e;
                if (pq.contains(w)) pq.decreaseKey(w, distTo[w]);
                else                pq.insert(w, distTo[w]);
            }
        }
    }

    /**
     * Returns the edges in a minimum spanning tree (or forest).
     * @return the edges in a minimum spanning tree (or forest) as
     *    an iterable of edges
     */
    public Iterable<Edge> edges() {
        Queue<Edge> mst = new Queue<Edge>();
        for (int v = 0; v < edgeTo.length; v++) {
            Edge e = edgeTo[v];
            if (e != null) {
                mst.enqueue(e);
            }
        }
        return mst;
    }

    /**
     * Returns the sum of the edge weights in a minimum spanning tree (or forest).
     * @return the sum of the edge weights in a minimum spanning tree (or forest)
     */
    public double weight() {
        double weight = 0.0;
        for (Edge e : edges())
            weight += e.weight();
        return weight;
    }

    // check optimality conditions (takes time proportional to E V lg* V)
    private boolean check(EdgeWeightedGraph graph) {

        // check weight
        double totalWeight = 0.0;
        for (Edge e : edges()) {
            totalWeight += e.weight();
        }
        if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {
            System.err.printf("Weight of edges does not equal weight(): %f vs. %f", totalWeight, weight());
            return false;
        }

        // check that it is acyclic
        UF uf = new UF(graph.V());
        for (Edge e : edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) == uf.find(w)) {
                System.err.println("Not a forest");
                return false;
            }
            uf.union(v, w);
        }

        // check that it is a spanning forest
        for (Edge e : graph.edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) != uf.find(w)) {
                System.err.println("Not a spanning forest");
                return false;
            }
        }

        // check that it is a minimal spanning forest (cut optimality conditions)
        for (Edge e : edges()) {

            // all edges in MST except e
            uf = new UF(graph.V());
            for (Edge f : edges()) {
                int x = f.either(), y = f.other(x);
                if (f != e) uf.union(x, y);
            }

            // check that e is min weight edge in crossing cut
            for (Edge f : graph.edges()) {
                int x = f.either(), y = f.other(x);
                if (uf.find(x) != uf.find(y)) {
                    if (f.weight() < e.weight()) {
                        System.err.println("Edge " + f + " violates cut optimality conditions");
                        return false;
                    }
                }
            }

        }

        return true;
    }

    /**
     * Unit tests the {@code PrimMST} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        In in = new In(args[0]);
        EdgeWeightedGraph graph = new EdgeWeightedGraph(in);
        PrimMST mst = new PrimMST(graph);
        for (Edge e : mst.edges()) {
            StdOut.println(e);
        }
        StdOut.printf("%.5f", mst.weight());
    }

}


Question:
Minimum spanning forest. Develop versions of Kruskal's algorithms that compute
the minimum spanning forest of an edge-weighted graph that
is not necessarily connected.

Answer:
/******************************************************************************
 *  Compilation:  javac KruskalMST.java
 *  Execution:    java  KruskalMST filename.txt
 *  Dependencies: EdgeWeightedGraph.java Edge.java Queue.java MinPQ.java
 *                UF.java In.java StdOut.java
 *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt
 *
 *  Compute a minimum spanning forest using Kruskal's algorithm.
 *
 *  %  java KruskalMST tinyEWG.txt
 *  0-7 0.16000
 *  2-3 0.17000
 *  1-7 0.19000
 *  0-2 0.26000
 *  5-7 0.28000
 *  4-5 0.35000
 *  6-2 0.40000
 *  1.81000
 *
 *  % java KruskalMST mediumEWG.txt
 *  168-231 0.00268
 *  151-208 0.00391
 *  7-157   0.00516
 *  122-205 0.00647
 *  8-152   0.00702
 *  156-219 0.00745
 *  28-198  0.00775
 *  38-126  0.00845
 *  10-123  0.00886
 *  ...
 *  10.46351
 *
 ******************************************************************************/

import java.util.Arrays;

/**
 *  The {@code KruskalMST} class represents a data type for computing a
 *  minimum spanning tree in an edge-weighted graph.
 *  The edge weights can be positive, zero, or negative and need not
 *  be distinct. If the graph is not connected, it computes a minimum
 *  spanning forest, which is the union of minimum spanning trees
 *  in each connected component. The {@code weight()} method returns the
 *  weight of a minimum spanning tree and the {@code edges()} method
 *  returns its edges.
 *

 *  This implementation uses Kruskal's algorithm and the
 *  union-find data type.
 *  The constructor takes Θ(E log E) time in
 *  the worst case.
 *  Each instance method takes Θ(1) time.
 *  It uses Θ(E) extra space (not including the graph).
 *

 *  This {@code weight()} method correctly computes the weight of the MST
 *  if all arithmetic performed is without floating-point rounding error
 *  or arithmetic overflow.
 *  This is the case if all edge weights are non-negative integers
 *  and the weight of the MST does not exceed 252.
 *

 *  For additional documentation,
 *  see Section 4.3 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *  For alternate implementations, see {@link LazyPrimMST}, {@link PrimMST},
 *  and {@link BoruvkaMST}.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class KruskalMST {
    private static final double FLOATING_POINT_EPSILON = 1.0E-12;

    private double weight;                        // weight of MST
    private Queue<Edge> mst = new Queue<Edge>();  // edges in MST

    /**
     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.
     * @param graph the edge-weighted graph
     */
    public KruskalMST(EdgeWeightedGraph graph) {

        // create array of edges, sorted by weight
        Edge[] edges = new Edge[graph.E()];
        int t = 0;
        for (Edge e: graph.edges()) {
            edges[t++] = e;
        }
        Arrays.sort(edges);

        // run greedy algorithm
        UF uf = new UF(graph.V());
        for (int i = 0; i < graph.E() && mst.size() < graph.V() - 1; i++) {
            Edge e = edges[i];
            int v = e.either();
            int w = e.other(v);

            // v-w does not create a cycle
            if (uf.find(v) != uf.find(w)) {
                uf.union(v, w);     // merge v and w components
                mst.enqueue(e);     // add edge e to mst
                weight += e.weight();
            }
        }

        // check optimality conditions
        assert check(graph);
    }

    /**
     * Returns the edges in a minimum spanning tree (or forest).
     * @return the edges in a minimum spanning tree (or forest) as
     *    an iterable of edges
     */
    public Iterable<Edge> edges() {
        return mst;
    }

    /**
     * Returns the sum of the edge weights in a minimum spanning tree (or forest).
     * @return the sum of the edge weights in a minimum spanning tree (or forest)
     */
    public double weight() {
        return weight;
    }

    // check optimality conditions (takes time proportional to E V lg* V)
    private boolean check(EdgeWeightedGraph graph) {

        // check total weight
        double total = 0.0;
        for (Edge e : edges()) {
            total += e.weight();
        }
        if (Math.abs(total - weight()) > FLOATING_POINT_EPSILON) {
            System.err.printf("Weight of edges does not equal weight(): %f vs. %f", total, weight());
            return false;
        }

        // check that it is acyclic
        UF uf = new UF(graph.V());
        for (Edge e : edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) == uf.find(w)) {
                System.err.println("Not a forest");
                return false;
            }
            uf.union(v, w);
        }

        // check that it is a spanning forest
        for (Edge e : graph.edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) != uf.find(w)) {
                System.err.println("Not a spanning forest");
                return false;
            }
        }

        // check that it is a minimal spanning forest (cut optimality conditions)
        for (Edge e : edges()) {

            // all edges in MST except e
            uf = new UF(graph.V());
            for (Edge f : mst) {
                int x = f.either(), y = f.other(x);
                if (f != e) uf.union(x, y);
            }

            // check that e is min weight edge in crossing cut
            for (Edge f : graph.edges()) {
                int x = f.either(), y = f.other(x);
                if (uf.find(x) != uf.find(y)) {
                    if (f.weight() < e.weight()) {
                        System.err.println("Edge " + f + " violates cut optimality conditions");
                        return false;
                    }
                }
            }

        }

        return true;
    }

    /**
     * Unit tests the {@code KruskalMST} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        In in = new In(args[0]);
        EdgeWeightedGraph G = new EdgeWeightedGraph(in);
        KruskalMST mst = new KruskalMST(G);
        for (Edge e : mst.edges()) {
            StdOut.println(e);
        }
        StdOut.printf("%.5f", mst.weight());
    }

}


Question: Certification. Write a method check() that uses the following cut optimality conditions to verify that a proposed set of edges is in fact an MST: A set of edges is an MST if it is a spanning tree and every edge is a minimum-weight edge in the cut defined by removing that edge from the tree. What is the order of growth of the running time of your method?

Answer:
/******************************************************************************
 *  Compilation:  javac KruskalMST.java
 *  Execution:    java  KruskalMST filename.txt
 *  Dependencies: EdgeWeightedGraph.java Edge.java Queue.java MinPQ.java
 *                UF.java In.java StdOut.java
 *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt
 *
 *  Compute a minimum spanning forest using Kruskal's algorithm.
 *
 *  %  java KruskalMST tinyEWG.txt
 *  0-7 0.16000
 *  2-3 0.17000
 *  1-7 0.19000
 *  0-2 0.26000
 *  5-7 0.28000
 *  4-5 0.35000
 *  6-2 0.40000
 *  1.81000
 *
 *  % java KruskalMST mediumEWG.txt
 *  168-231 0.00268
 *  151-208 0.00391
 *  7-157   0.00516
 *  122-205 0.00647
 *  8-152   0.00702
 *  156-219 0.00745
 *  28-198  0.00775
 *  38-126  0.00845
 *  10-123  0.00886
 *  ...
 *  10.46351
 *
 ******************************************************************************/

import java.util.Arrays;

/**
 *  The {@code KruskalMST} class represents a data type for computing a
 *  minimum spanning tree in an edge-weighted graph.
 *  The edge weights can be positive, zero, or negative and need not
 *  be distinct. If the graph is not connected, it computes a minimum
 *  spanning forest, which is the union of minimum spanning trees
 *  in each connected component. The {@code weight()} method returns the
 *  weight of a minimum spanning tree and the {@code edges()} method
 *  returns its edges.
 *

 *  This implementation uses Kruskal's algorithm and the
 *  union-find data type.
 *  The constructor takes Θ(E log E) time in
 *  the worst case.
 *  Each instance method takes Θ(1) time.
 *  It uses Θ(E) extra space (not including the graph).
 *

 *  This {@code weight()} method correctly computes the weight of the MST
 *  if all arithmetic performed is without floating-point rounding error
 *  or arithmetic overflow.
 *  This is the case if all edge weights are non-negative integers
 *  and the weight of the MST does not exceed 252.
 *

 *  For additional documentation,
 *  see Section 4.3 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *  For alternate implementations, see {@link LazyPrimMST}, {@link PrimMST},
 *  and {@link BoruvkaMST}.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class KruskalMST {
    private static final double FLOATING_POINT_EPSILON = 1.0E-12;

    private double weight;                        // weight of MST
    private Queue<Edge> mst = new Queue<Edge>();  // edges in MST

    /**
     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.
     * @param graph the edge-weighted graph
     */
    public KruskalMST(EdgeWeightedGraph graph) {

        // create array of edges, sorted by weight
        Edge[] edges = new Edge[graph.E()];
        int t = 0;
        for (Edge e: graph.edges()) {
            edges[t++] = e;
        }
        Arrays.sort(edges);

        // run greedy algorithm
        UF uf = new UF(graph.V());
        for (int i = 0; i < graph.E() && mst.size() < graph.V() - 1; i++) {
            Edge e = edges[i];
            int v = e.either();
            int w = e.other(v);

            // v-w does not create a cycle
            if (uf.find(v) != uf.find(w)) {
                uf.union(v, w);     // merge v and w components
                mst.enqueue(e);     // add edge e to mst
                weight += e.weight();
            }
        }

        // check optimality conditions
        assert check(graph);
    }

    /**
     * Returns the edges in a minimum spanning tree (or forest).
     * @return the edges in a minimum spanning tree (or forest) as
     *    an iterable of edges
     */
    public Iterable<Edge> edges() {
        return mst;
    }

    /**
     * Returns the sum of the edge weights in a minimum spanning tree (or forest).
     * @return the sum of the edge weights in a minimum spanning tree (or forest)
     */
    public double weight() {
        return weight;
    }

    // check optimality conditions (takes time proportional to E V lg* V)
    private boolean check(EdgeWeightedGraph graph) {

        // check total weight
        double total = 0.0;
        for (Edge e : edges()) {
            total += e.weight();
        }
        if (Math.abs(total - weight()) > FLOATING_POINT_EPSILON) {
            System.err.printf("Weight of edges does not equal weight(): %f vs. %f", total, weight());
            return false;
        }

        // check that it is acyclic
        UF uf = new UF(graph.V());
        for (Edge e : edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) == uf.find(w)) {
                System.err.println("Not a forest");
                return false;
            }
            uf.union(v, w);
        }

        // check that it is a spanning forest
        for (Edge e : graph.edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) != uf.find(w)) {
                System.err.println("Not a spanning forest");
                return false;
            }
        }

        // check that it is a minimal spanning forest (cut optimality conditions)
        for (Edge e : edges()) {

            // all edges in MST except e
            uf = new UF(graph.V());
            for (Edge f : mst) {
                int x = f.either(), y = f.other(x);
                if (f != e) uf.union(x, y);
            }

            // check that e is min weight edge in crossing cut
            for (Edge f : graph.edges()) {
                int x = f.either(), y = f.other(x);
                if (uf.find(x) != uf.find(y)) {
                    if (f.weight() < e.weight()) {
                        System.err.println("Edge " + f + " violates cut optimality conditions");
                        return false;
                    }
                }
            }

        }

        return true;
    }

    /**
     * Unit tests the {@code KruskalMST} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        In in = new In(args[0]);
        EdgeWeightedGraph G = new EdgeWeightedGraph(in);
        KruskalMST mst = new KruskalMST(G);
        for (Edge e : mst.edges()) {
            StdOut.println(e);
        }
        StdOut.printf("%.5f", mst.weight());
    }

}


Question: Boruvka's algorithm. Develop an implementation BoruvkaMST.java of Boruvka's algorithm: Build an MST by adding edges to a growing forest of trees, as in Kruskal's algorithm, but in stages. At each stage, find the minimum-weight edge that connects each tree to a different one, then add all such edges to the MST. Assume that the edge weights are all different, to avoid cycles. Hint: Maintain in a vertex-indexed array to identify the edge that connects each component to its nearest neighbor, and use the union-find data structure. Remark. There are a most log V phases since number of trees decreases by at least a factor of 2 in each phase. Attractive because it is efficient and can be run in parallel.

Answer:
/******************************************************************************
 *  Compilation:  javac BoruvkaMST.java
 *  Execution:    java BoruvkaMST filename.txt
 *  Dependencies: EdgeWeightedGraph.java Edge.java Bag.java
 *                UF.java In.java StdOut.java
 *  Data files:   https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
 *                https://algs4.cs.princeton.edu/43mst/largeEWG.txt
 *
 *  Compute a minimum spanning forest using Boruvka's algorithm.
 *
 *  % java BoruvkaMST tinyEWG.txt
 *  0-2 0.26000
 *  6-2 0.40000
 *  5-7 0.28000
 *  4-5 0.35000
 *  2-3 0.17000
 *  1-7 0.19000
 *  0-7 0.16000
 *  1.81000
 *
 ******************************************************************************/

/**
 *  The {@code BoruvkaMST} class represents a data type for computing a
 *  minimum spanning tree in an edge-weighted graph.
 *  The edge weights can be positive, zero, or negative and need not
 *  be distinct. If the graph is not connected, it computes a minimum
 *  spanning forest, which is the union of minimum spanning trees
 *  in each connected component. The {@code weight()} method returns the
 *  weight of a minimum spanning tree and the {@code edges()} method
 *  returns its edges.
 *

 *  This implementation uses Boruvka's algorithm and the union-find
 *  data type.
 *  The constructor takes Θ(E log V) time in
 *  the worst case, where V is the number of vertices and
 *  E is the number of edges.
 *  Each instance method takes Θ(1) time.
 *  It uses Θ(V) extra space (not including the
 *  edge-weighted graph).
 *

 *  This {@code weight()} method correctly computes the weight of the MST
 *  if all arithmetic performed is without floating-point rounding error
 *  or arithmetic overflow.
 *  This is the case if all edge weights are non-negative integers
 *  and the weight of the MST does not exceed 252.
 *

 *  For additional documentation,
 *  see Section 4.3 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *  For alternate implementations, see {@link LazyPrimMST}, {@link PrimMST},
 *  and {@link KruskalMST}.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class BoruvkaMST {
    private static final double FLOATING_POINT_EPSILON = 1.0E-12;

    private Bag<Edge> mst = new Bag<Edge>();    // edges in MST
    private double weight;                      // weight of MST

    /**
     * Compute a minimum spanning tree (or forest) of an edge-weighted graph.
     * @param graph the edge-weighted graph
     */
    public BoruvkaMST(EdgeWeightedGraph graph) {
        UF uf = new UF(graph.V());

        // repeat at most log V times or until we have V-1 edges
        for (int t = 1; t < graph.V() && mst.size() < graph.V() - 1; t = t + t) {

            // foreach tree in forest, find closest edge
            // if edge weights are equal, ties are broken in favor of first edge in graph.edges()
            Edge[] closest = new Edge[graph.V()];
            for (Edge e : graph.edges()) {
                int v = e.either(), w = e.other(v);
                int i = uf.find(v), j = uf.find(w);
                if (i == j) continue;   // same tree
                if (closest[i] == null || less(e, closest[i])) closest[i] = e;
                if (closest[j] == null || less(e, closest[j])) closest[j] = e;
            }

            // add newly discovered edges to MST
            for (int i = 0; i < graph.V(); i++) {
                Edge e = closest[i];
                if (e != null) {
                    int v = e.either(), w = e.other(v);
                    // don't add the same edge twice
                    if (uf.find(v) != uf.find(w)) {
                        mst.add(e);
                        weight += e.weight();
                        uf.union(v, w);
                    }
                }
            }
        }

        // check optimality conditions
        assert check(graph);
    }

    /**
     * Returns the edges in a minimum spanning tree (or forest).
     * @return the edges in a minimum spanning tree (or forest) as
     *    an iterable of edges
     */
    public Iterable<Edge> edges() {
        return mst;
    }

    /**
     * Returns the sum of the edge weights in a minimum spanning tree (or forest).
     * @return the sum of the edge weights in a minimum spanning tree (or forest)
     */
    public double weight() {
        return weight;
    }

    // is the weight of edge e strictly less than that of edge f?
    private static boolean less(Edge e, Edge f) {
        return e.compareTo(f) < 0;
    }

    // check optimality conditions (takes time proportional to E V lg* V)
    private boolean check(EdgeWeightedGraph graph) {

        // check weight
        double totalWeight = 0.0;
        for (Edge e : edges()) {
            totalWeight += e.weight();
        }
        if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {
            System.err.printf("Weight of edges does not equal weight(): %f vs. %f", totalWeight, weight());
            return false;
        }

        // check that it is acyclic
        UF uf = new UF(graph.V());
        for (Edge e : edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) == uf.find(w)) {
                System.err.println("Not a forest");
                return false;
            }
            uf.union(v, w);
        }

        // check that it is a spanning forest
        for (Edge e : graph.edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.find(v) != uf.find(w)) {
                System.err.println("Not a spanning forest");
                return false;
            }
        }

        // check that it is a minimal spanning forest (cut optimality conditions)
        for (Edge e : edges()) {

            // all edges in MST except e
            uf = new UF(graph.V());
            for (Edge f : mst) {
                int x = f.either(), y = f.other(x);
                if (f != e) uf.union(x, y);
            }

            // check that e is min weight edge in crossing cut
            for (Edge f : graph.edges()) {
                int x = f.either(), y = f.other(x);
                if (uf.find(x) != uf.find(y)) {
                    if (f.weight() < e.weight()) {
                        System.err.println("Edge " + f + " violates cut optimality conditions");
                        return false;
                    }
                }
            }

        }

        return true;
    }

    /**
     * Unit tests the {@code BoruvkaMST} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        In in = new In(args[0]);
        EdgeWeightedGraph graph = new EdgeWeightedGraph(in);
        BoruvkaMST mst = new BoruvkaMST(graph);
        for (Edge e : mst.edges()) {
            StdOut.println(e);
        }
        StdOut.printf("%.5f", mst.weight());
    }

}


Question: Provide an implementation of toString() for EdgeWeightedDigraph.java.

Answer:
/******************************************************************************
 *  Compilation:  javac EdgeWeightedDigraph.java
 *  Execution:    java EdgeWeightedDigraph digraph.txt
 *  Dependencies: Bag.java DirectedEdge.java
 *  Data files:   https://algs4.cs.princeton.edu/44sp/tinyEWD.txt
 *                https://algs4.cs.princeton.edu/44sp/mediumEWD.txt
 *                https://algs4.cs.princeton.edu/44sp/largeEWD.txt
 *
 *  An edge-weighted digraph, implemented using adjacency lists.
 *
 ******************************************************************************/

import java.util.NoSuchElementException;

/**
 *  The {@code EdgeWeightedDigraph} class represents an edge-weighted
 *  digraph of vertices named 0 through V - 1, where each
 *  directed edge is of type {@link DirectedEdge} and has a real-valued weight.
 *  It supports the following two primary operations: add a directed edge
 *  to the digraph and iterate over all edges incident from a given vertex.
 *  It also provides methods for returning the indegree or outdegree of a
 *  vertex, the number of vertices V in the digraph, and
 *  the number of edges E in the digraph.
 *  Parallel edges and self-loops are permitted.
 *

 *  This implementation uses an adjacency-lists representation, which
 *  is a vertex-indexed array of {@link Bag} objects.
 *  It uses Θ(E + V) space, where E is
 *  the number of edges and V is the number of vertices.
 *  All instance methods take Θ(1) time. (Though, iterating over
 *  the edges returned by {@link #adj(int)} takes time proportional
 *  to the outdegree of the vertex.)
 *  Constructing an empty edge-weighted digraph with V vertices
 *  takes Θ(V) time; constructing an edge-weighted digraph
 *  with E edges and V vertices takes
 *  Θ(E + V) time.
 *

 *  For additional documentation,
 *  see Section 4.4 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class EdgeWeightedDigraph {
    private static final String NEWLINE = System.getProperty("line.separator");

    private final int V;                // number of vertices in this digraph
    private int E;                      // number of edges in this digraph
    private Bag<DirectedEdge>[] adj;    // adj[v] = adjacency list for vertex v
    private int[] indegree;             // indegree[v] = indegree of vertex v

    /**
     * Initializes an empty edge-weighted digraph with {@code V} vertices and 0 edges.
     *
     * @param  V the number of vertices
     * @throws IllegalArgumentException if {@code V < 0}
     */
    public EdgeWeightedDigraph(int V) {
        if (V < 0) throw new IllegalArgumentException("Number of vertices in a Digraph must be non-negative");
        this.V = V;
        this.E = 0;
        this.indegree = new int[V];
        adj = (Bag<DirectedEdge>[]) new Bag[V];
        for (int v = 0; v < V; v++)
            adj[v] = new Bag<DirectedEdge>();
    }

    /**
     * Initializes a random edge-weighted digraph with {@code V} vertices and E edges.
     *
     * @param  V the number of vertices
     * @param  E the number of edges
     * @throws IllegalArgumentException if {@code V < 0}
     * @throws IllegalArgumentException if {@code E < 0}
     */
    public EdgeWeightedDigraph(int V, int E) {
        this(V);
        if (E < 0) throw new IllegalArgumentException("Number of edges in a Digraph must be non-negative");
        for (int i = 0; i < E; i++) {
            int v = StdRandom.uniformInt(V);
            int w = StdRandom.uniformInt(V);
            double weight = 0.01 * StdRandom.uniformInt(100);
            DirectedEdge e = new DirectedEdge(v, w, weight);
            addEdge(e);
        }
    }

    /**
     * Initializes an edge-weighted digraph from the specified input stream.
     * The format is the number of vertices V,
     * followed by the number of edges E,
     * followed by E pairs of vertices and edge weights,
     * with each entry separated by whitespace.
     *
     * @param  in the input stream
     * @throws IllegalArgumentException if {@code in} is {@code null}
     * @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range
     * @throws IllegalArgumentException if the number of vertices or edges is negative
     */
    public EdgeWeightedDigraph(In in) {
        if (in == null) throw new IllegalArgumentException("argument is null");
        try {
            this.V = in.readInt();
            if (V < 0) throw new IllegalArgumentException("number of vertices in a Digraph must be non-negative");
            indegree = new int[V];
            adj = (Bag<DirectedEdge>[]) new Bag[V];
            for (int v = 0; v < V; v++) {
                adj[v] = new Bag<DirectedEdge>();
            }

            int E = in.readInt();
            if (E < 0) throw new IllegalArgumentException("Number of edges must be non-negative");
            for (int i = 0; i < E; i++) {
                int v = in.readInt();
                int w = in.readInt();
                validateVertex(v);
                validateVertex(w);
                double weight = in.readDouble();
                addEdge(new DirectedEdge(v, w, weight));
            }
        }
        catch (NoSuchElementException e) {
            throw new IllegalArgumentException("invalid input format in EdgeWeightedDigraph constructor", e);
        }
    }

    /**
     * Initializes a new edge-weighted digraph that is a deep copy of {@code G}.
     *
     * @param  G the edge-weighted digraph to copy
     */
    public EdgeWeightedDigraph(EdgeWeightedDigraph G) {
        this(G.V());
        this.E = G.E();
        for (int v = 0; v < G.V(); v++)
            this.indegree[v] = G.indegree(v);
        for (int v = 0; v < G.V(); v++) {
            // reverse so that adjacency list is in same order as original
            Stack<DirectedEdge> reverse = new Stack<DirectedEdge>();
            for (DirectedEdge e : G.adj[v]) {
                reverse.push(e);
            }
            for (DirectedEdge e : reverse) {
                adj[v].add(e);
            }
        }
    }

    /**
     * Returns the number of vertices in this edge-weighted digraph.
     *
     * @return the number of vertices in this edge-weighted digraph
     */
    public int V() {
        return V;
    }

    /**
     * Returns the number of edges in this edge-weighted digraph.
     *
     * @return the number of edges in this edge-weighted digraph
     */
    public int E() {
        return E;
    }

    // throw an IllegalArgumentException unless {@code 0 <= v < V}
    private void validateVertex(int v) {
        if (v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
    }

    /**
     * Adds the directed edge {@code e} to this edge-weighted digraph.
     *
     * @param  e the edge
     * @throws IllegalArgumentException unless endpoints of edge are between {@code 0}
     *         and {@code V-1}
     */
    public void addEdge(DirectedEdge e) {
        int v = e.from();
        int w = e.to();
        validateVertex(v);
        validateVertex(w);
        adj[v].add(e);
        indegree[w]++;
        E++;
    }

    /**
     * Returns the directed edges incident from vertex {@code v}.
     *
     * @param  v the vertex
     * @return the directed edges incident from vertex {@code v} as an Iterable
     * @throws IllegalArgumentException unless {@code 0 <= v < V}
     */
    public Iterable<DirectedEdge> adj(int v) {
        validateVertex(v);
        return adj[v];
    }

    /**
     * Returns the number of directed edges incident from vertex {@code v}.
     * This is known as the outdegree of vertex {@code v}.
     *
     * @param  v the vertex
     * @return the outdegree of vertex {@code v}
     * @throws IllegalArgumentException unless {@code 0 <= v < V}
     */
    public int outdegree(int v) {
        validateVertex(v);
        return adj[v].size();
    }

    /**
     * Returns the number of directed edges incident to vertex {@code v}.
     * This is known as the indegree of vertex {@code v}.
     *
     * @param  v the vertex
     * @return the indegree of vertex {@code v}
     * @throws IllegalArgumentException unless {@code 0 <= v < V}
     */
    public int indegree(int v) {
        validateVertex(v);
        return indegree[v];
    }

    /**
     * Returns all directed edges in this edge-weighted digraph.
     * To iterate over the edges in this edge-weighted digraph, use foreach notation:
     * {@code for (DirectedEdge e : G.edges())}.
     *
     * @return all edges in this edge-weighted digraph, as an iterable
     */
    public Iterable<DirectedEdge> edges() {
        Bag<DirectedEdge> list = new Bag<DirectedEdge>();
        for (int v = 0; v < V; v++) {
            for (DirectedEdge e : adj(v)) {
                list.add(e);
            }
        }
        return list;
    }

    /**
     * Returns a string representation of this edge-weighted digraph.
     *
     * @return the number of vertices V, followed by the number of edges E,
     *         followed by the V adjacency lists of edges
     */
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append(V + " " + E + NEWLINE);
        for (int v = 0; v < V; v++) {
            s.append(v + ": ");
            for (DirectedEdge e : adj[v]) {
                s.append(e + "  ");
            }
            s.append(NEWLINE);
        }
        return s.toString();
    }

    /**
     * Returns a string representation of this edge-weighted digraph in DOT format,
     * suitable for visualization with Graphviz.
     *
     * To visualize the graph, install Graphviz (e.g., "brew install graphviz").
     * Then use one of the graph visualization tools
     *    - dot    (hierarchical or layer drawing)
     *    - neato  (spring model)
     *    - fdp    (force-directed placement)
     *    - sfdp   (scalable force-directed placement)
     *    - twopi  (radial layout)
     *
     * For example, the following commands will create graph drawings in SVG
     * and PDF formats
     *    - dot input.dot -Tsvg -o output.svg
     *    - dot input.dot -Tpdf -o output.pdf
     *
     * To change the digraph attributes (e.g., vertex and edge shapes, arrows, colors)
     *  in the DOT format, see https://graphviz.org/doc/info/lang.html
     *
     * @return a string representation of this edge-weighted digraph in DOT format
     */
    public String toDot() {
        StringBuilder s = new StringBuilder();
        s.append("digraph {" + NEWLINE);
        s.append("node[shape=circle, style=filled, fixedsize=true, width=0.3, fontsize=\"10pt\"]" + NEWLINE);
        s.append("edge[arrowhead=normal, fontsize=\"9pt\"]" + NEWLINE);
        for (int v = 0; v < V; v++) {
            for (DirectedEdge e : adj[v]) {
                int w = e.to();
                s.append(v + " -> " + w + " [label=\"" + e.weight() + "\"]" + NEWLINE);
            }
        }
        s.append("}" + NEWLINE);
        return s.toString();
    }

    /**
     * Unit tests the {@code EdgeWeightedDigraph} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        In in = new In(args[0]);
        EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
        StdOut.println(G);
    }

}


Question: Adapt the Topological classes from Section 4.2 to use the EdgeweightedDigraph and DirectedEdge APIs of this section, thus implementing Topological.java.

Answer:
/******************************************************************************
 *  Compilation:  javac Topological.java
 *  Execution:    java  Topological filename.txt delimiter
 *  Dependencies: Digraph.java DepthFirstOrder.java DirectedCycle.java
 *                EdgeWeightedDigraph.java EdgeWeightedDirectedCycle.java
 *                SymbolDigraph.java
 *  Data files:   https://algs4.cs.princeton.edu/42digraph/jobs.txt
 *
 *  Compute topological ordering of a DAG or edge-weighted DAG.
 *  Runs in O(E + V) time.
 *
 *  % java Topological jobs.txt "/"
 *  Calculus
 *  Linear Algebra
 *  Introduction to CS
 *  Advanced Programming
 *  Algorithms
 *  Theoretical CS
 *  Artificial Intelligence
 *  Robotics
 *  Machine Learning
 *  Neural Networks
 *  Databases
 *  Scientific Computing
 *  Computational Biology
 *
 ******************************************************************************/

/**
 *  The {@code Topological} class represents a data type for
 *  determining a topological order of a directed acyclic graph (DAG).
 *  A digraph has a topological order if and only if it is a DAG.
 *  The hasOrder operation determines whether the digraph has
 *  a topological order, and if so, the order operation
 *  returns one.
 *

 *  This implementation uses depth-first search.
 *  The constructor takes Θ(V + E) time in the
 *  worst case, where V is the number of vertices and E
 *  is the number of edges.
 *  Each instance method takes Θ(1) time.
 *  It uses Θ(V) extra space (not including the digraph).
 *

 *  See {@link DirectedCycle}, {@link DirectedCycleX}, and
 *  {@link EdgeWeightedDirectedCycle} for computing a directed cycle
 *  if the digraph is not a DAG.
 *  See {@link TopologicalX} for a nonrecursive, queue-based algorithm
 *  for computing a topological order of a DAG.
 *

 *  For additional documentation,
 *  see Section 4.2 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class Topological {
    private Iterable<Integer> order;  // topological order
    private int[] rank;               // rank[v] = rank of vertex v in order

    /**
     * Determines whether the {@code digraph} has a topological order and, if so,
     * finds such a topological order.
     * @param digraph the digraph
     */
    public Topological(Digraph digraph) {
        DirectedCycle finder = new DirectedCycle(digraph);
        if (!finder.hasCycle()) {
            DepthFirstOrder dfs = new DepthFirstOrder(digraph);
            order = dfs.reversePost();
            rank = new int[digraph.V()];
            int i = 0;
            for (int v : order)
                rank[v] = i++;
        }
    }

    /**
     * Determines whether the edge-weighted digraph {@code digraph} has a topological
     * order and, if so, finds such an order.
     * @param digraph the edge-weighted digraph
     */
    public Topological(EdgeWeightedDigraph digraph) {
        EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(digraph);
        if (!finder.hasCycle()) {
            DepthFirstOrder dfs = new DepthFirstOrder(digraph);
            order = dfs.reversePost();
        }
    }

    /**
     * Returns a topological order if the digraph has a topological order,
     * and {@code null} otherwise.
     * @return a topological order of the vertices (as an iterable) if the
     *    digraph has a topological order (or equivalently, if the digraph is a DAG),
     *    and {@code null} otherwise
     */
    public Iterable<Integer> order() {
        return order;
    }

    /**
     * Does the digraph have a topological order?
     * @return {@code true} if the digraph has a topological order (or equivalently,
     *    if the digraph is a DAG), and {@code false} otherwise
     */
    public boolean hasOrder() {
        return order != null;
    }

    /**
     * Does the digraph have a topological order?
     * @return {@code true} if the digraph has a topological order (or equivalently,
     *    if the digraph is a DAG), and {@code false} otherwise
     * @deprecated Replaced by {@link #hasOrder()}.
     */
    @Deprecated
    public boolean isDAG() {
        return hasOrder();
    }

    /**
     * The rank of vertex {@code v} in the topological order;
     * -1 if the digraph is not a DAG
     *
     * @param v the vertex
     * @return the position of vertex {@code v} in a topological order
     *    of the digraph; -1 if the digraph is not a DAG
     * @throws IllegalArgumentException unless {@code 0 <= v < V}
     */
    public int rank(int v) {
        validateVertex(v);
        if (hasOrder()) return rank[v];
        else            return -1;
    }

    // throw an IllegalArgumentException unless {@code 0 <= v < V}
    private void validateVertex(int v) {
        int V = rank.length;
        if (v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
    }

    /**
     * Unit tests the {@code Topological} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        String filename  = args[0];
        String delimiter = args[1];
        SymbolDigraph sg = new SymbolDigraph(filename, delimiter);
        Topological topological = new Topological(sg.digraph());
        for (int v : topological.order()) {
            StdOut.println(sg.nameOf(v));
        }
    }

}


Question: Longest paths in DAGs. Develop an implementation AcyclicLP.java that can solve the longest-paths problem in edge-weighted DAGs.

Answer:
/******************************************************************************
 *  Compilation:  javac AcyclicLP.java
 *  Execution:    java AcyclicP V E
 *  Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Topological.java
 *  Data files:   https://algs4.cs.princeton.edu/44sp/tinyEWDAG.txt
 *
 *  Computes longest paths in an edge-weighted acyclic digraph.
 *
 *  Remark: should probably check that graph is a DAG before running
 *
 *  % java AcyclicLP tinyEWDAG.txt 5
 *  5 to 0 (2.44)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93   4->0  0.38
 *  5 to 1 (0.32)  5->1  0.32
 *  5 to 2 (2.77)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93   4->7  0.37   7->2  0.34
 *  5 to 3 (0.61)  5->1  0.32   1->3  0.29
 *  5 to 4 (2.06)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93
 *  5 to 5 (0.00)
 *  5 to 6 (1.13)  5->1  0.32   1->3  0.29   3->6  0.52
 *  5 to 7 (2.43)  5->1  0.32   1->3  0.29   3->6  0.52   6->4  0.93   4->7  0.37
 *
 ******************************************************************************/

/**
 *  The {@code AcyclicLP} class represents a data type for solving the
 *  single-source longest paths problem in edge-weighted directed
 *  acyclic graphs (DAGs). The edge weights can be positive, negative, or zero.
 *

 *  This implementation uses a topological-sort based algorithm.
 *  The constructor takes Θ(V + E) time in the
 *  worst case, where V is the number of vertices and
 *  E is the number of edges.
 *  Each instance method takes Θ(1) time.
 *  It uses Θ(V) extra space (not including the
 *  edge-weighted digraph).
 *

 *  This correctly computes longest paths if all arithmetic performed is
 *  without floating-point rounding error or arithmetic overflow.
 *  This is the case if all edge weights are integers and if none of the
 *  intermediate results exceeds 252. Since all intermediate
 *  results are sums of edge weights, they are bounded by V C,
 *  where V is the number of vertices and C is the maximum
 *  absolute value of any edge weight.
 *

 *  For additional documentation,
 *  see Section 4.4 of
 *  Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
 *
 *  @author Robert Sedgewick
 *  @author Kevin Wayne
 */
public class AcyclicLP {
    private double[] distTo;          // distTo[v] = distance  of longest s->v path
    private DirectedEdge[] edgeTo;    // edgeTo[v] = last edge on longest s->v path

    /**
     * Computes a longest paths tree from {@code s} to every other vertex in
     * the directed acyclic graph {@code digraph}.
     * @param digraph the acyclic digraph
     * @param s the source vertex
     * @throws IllegalArgumentException if the digraph is not acyclic
     * @throws IllegalArgumentException unless {@code 0 <= s < V}
     */
    public AcyclicLP(EdgeWeightedDigraph digraph, int s) {
        distTo = new double[digraph.V()];
        edgeTo = new DirectedEdge[digraph.V()];

        validateVertex(s);

        for (int v = 0; v < digraph.V(); v++)
            distTo[v] = Double.NEGATIVE_INFINITY;
        distTo[s] = 0.0;

        // relax vertices in topological order
        Topological topological = new Topological(digraph);
        if (!topological.hasOrder())
            throw new IllegalArgumentException("Digraph is not acyclic.");
        for (int v : topological.order()) {
            for (DirectedEdge e : digraph.adj(v))
                relax(e);
        }
    }

    // relax edge e, but update if you find a *longer* path
    private void relax(DirectedEdge e) {
        int v = e.from(), w = e.to();
        if (distTo[w] < distTo[v] + e.weight()) {
            distTo[w] = distTo[v] + e.weight();
            edgeTo[w] = e;
        }
    }

    /**
     * Returns the length of a longest path from the source vertex {@code s} to vertex {@code v}.
     * @param  v the destination vertex
     * @return the length of a longest path from the source vertex {@code s} to vertex {@code v};
     *         {@code Double.NEGATIVE_INFINITY} if no such path
     * @throws IllegalArgumentException unless {@code 0 <= v < V}
     */
    public double distTo(int v) {
        validateVertex(v);
        return distTo[v];
    }

    /**
     * Is there a path from the source vertex {@code s} to vertex {@code v}?
     * @param  v the destination vertex
     * @return {@code true} if there is a path from the source vertex
     *         {@code s} to vertex {@code v}, and {@code false} otherwise
     * @throws IllegalArgumentException unless {@code 0 <= v < V}
     */
    public boolean hasPathTo(int v) {
        validateVertex(v);
        return distTo[v] > Double.NEGATIVE_INFINITY;
    }

    /**
     * Returns a longest path from the source vertex {@code s} to vertex {@code v}.
     * @param  v the destination vertex
     * @return a longest path from the source vertex {@code s} to vertex {@code v}
     *         as an iterable of edges, and {@code null} if no such path
     * @throws IllegalArgumentException unless {@code 0 <= v < V}
     */
    public Iterable<DirectedEdge> pathTo(int v) {
        validateVertex(v);
        if (!hasPathTo(v)) return null;
        Stack<DirectedEdge> path = new Stack<DirectedEdge>();
        for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {
            path.push(e);
        }
        return path;
    }

    // throw an IllegalArgumentException unless {@code 0 <= v < V}
    private void validateVertex(int v) {
        int V = distTo.length;
        if (v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
    }

    /**
     * Unit tests the {@code AcyclicLP} data type.
     *
     * @param args the command-line arguments
     */
    public static void main(String[] args) {
        In in = new In(args[0]);
        int s = Integer.parseInt(args[1]);
        EdgeWeightedDigraph digraph = new EdgeWeightedDigraph(in);

        AcyclicLP lp = new AcyclicLP(digraph, s);

        for (int v = 0; v < digraph.V(); v++) {
            if (lp.hasPathTo(v)) {
                StdOut.printf("%d to %d (%.2f)  ", s, v, lp.distTo(v));
                for (DirectedEdge e : lp.pathTo(v)) {
                    StdOut.print(e + "   ");
                }
                StdOut.println();
            }
            else {
                StdOut.printf("%d to %d         no path", s, v);
            }
        }
    }
}


Question:
Give the value of each of the following expressions:
a. ( 0 + 15 ) / 2
b. 2.0e-6 * 100000000.1
c. true && false || true && true

Answer:
1.1.1
a) 7
b) 200.0000002
c) true


Question:
Give the type and value of each of the following expressions:
a. (1 + 2.236)/2
b. 1 + 2 + 3 + 4.0
c. 4.1 >= 4
d. 1 + 2 + "3"

Answer:
1.1.2
a) 1.618 -> double
b) 10.0 -> double
c) true -> boolean
d) 33 -> String


Question:
What (if anything) is wrong with each of the following statements?
a. if (a > b) then c = 0;
b. if a > b { c = 0; }
c. if (a > b) c = 0;
d. if (a > b) c = 0 else b = 0;

Answer:
1.1.4
a) No such keyword as "then" in Java language
b) Missing Parentheses on if conditional
c) Nothing wrong
d) Missing semicolon after the "then" clause


Question:
What does the following program print?
int f = 0;
int g = 1;
for (int i = 0; i <= 15; i++)
{
 StdOut.println(f);
 f = f + g;
 g = f - g;
}

Answer:
1.1.6

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610


Question:
Give the value printed by each of the following code fragments:
a. double t = 9.0;
 while (Math.abs(t - 9.0/t) > .001)
 t = (9.0/t + t) / 2.0;
 StdOut.printf("%.5f\n", t);
b. int sum = 0;
 for (int i = 1; i < 1000; i++)
 for (int j = 0; j < i; j++)
 sum++;
 StdOut.println(sum);
c. int sum = 0;
 for (int i = 1; i < 1000; i *= 2)
 for (int j = 0; j < N; j++)
 sum++;
 StdOut.println(sum);

Answer:
1.1.7
a) 3.00009
b) 499500
c) 10000


Question:
What do each of the following print?
a. System.out.println('b');
b. System.out.println('b' + 'c');
c. System.out.println((char) ('a' + 4));
Explain each outcome.

Answer:
1.1.8
a) b -> converts the char "b" to String and prints it
b) 197 -> sums the char codes of "b" and "c", converts to String and prints it
c) e -> sums the char code of "a" with 4, converts it to char and prints it


Question:
What is wrong with the following code fragment?
int[] a;
for (int i = 0; i < 10; i++)
 a[i] = i * i;

Answer:
1.1.10
The array was not initialized and will generate a compile-time error.


Question:
What does the following code fragment print?
int[] a = new int[10];
for (int i = 0; i < 10; i++)
 a[i] = 9 - i;
for (int i = 0; i < 10; i++)
 a[i] = a[a[i]];
for (int i = 0; i < 10; i++)
 System.out.println(i);

Answer:
1.1.12

0
1
2
3
4
4
3
2
1
0


Question:
Give the value of exR1(6):
public static String exR1(int n)
{
 if (n <= 0) return "";
 return exR1(n-3) + n + exR1(n-2) + n;
}

Answer:
1.1.16

311361142246


Question:
Criticize the following recursive function:
public static String exR2(int n)
{
 String s = exR2(n-3) + n + exR2(n-2) + n;
 if (n <= 0) return "";
 return s;
}

Answer:
1.1.17
The function never stops because it keeps calling itself on the first line, until a StackOverflowError occurs.


Question:
Consider the following recursive function:
public static int mystery(int a, int b)
{
 if (b == 0) return 0;
 if (b % 2 == 0) return mystery(a+a, b/2);
 return mystery(a+a, b/2) + a;
}
What are the values of mystery(2, 25) and mystery(3, 11)? Given positive integers a and b, describe what value mystery(a, b) computes. Answer the same question, but replace + with * and replace return 0 with return 1.

Answer:
1.1.18

mystery(2,25) is equal to 50
mystery(3,11) is equal to 33
mystery(a,b) computes a * b

mystery2(2,25) is equal to 33554432
mystery2(3,11) is equal to 177147
mystery2(a,b) computes a^b


Question:
Run the following program on your computer:
public class Fibonacci
{
 public static long F(int N)
 {
 if (N == 0) return 0;
 if (N == 1) return 1;
 return F(N-1) + F(N-2);
 }
 public static void main(String[] args)
 {
 for (int N = 0; N < 100; N++)
 StdOut.println(N + " " + F(N));
 }
}
What is the largest value of N for which this program takes less 1 hour to compute the value of F(N)? Develop a better implementation of F(N) that saves computed values in an array.

Answer:
1.1.19

The largest value of N that takes less than 1 hour to compute is 51.


Question: Use mathematical induction to prove that Euclid’s algorithm computes the greatest common divisor of any pair of nonnegative integers p and q.

Answer:
1.1.25

For all N E NaturalNumbers and for all nonnegative integers a <= N and b <= N, the Euclidean algorithm computes the greatest common divisor of a and b.

Proving that gcd(a, b) = gcd(b, a % b)

gcd(20,5) = gcd(5,0)

gcd(20,5) is 5
gcd(5,0) is also 5

http://math.stackexchange.com/questions/1274515/prove-that-euclids-algorithm-computes-the-gcd-of-any-pair-of-nonnegative-intege

https://www.whitman.edu/mathematics/higher_math_online/section03.03.html


Question:
Binomial distribution. Estimate the number of recursive calls that would be used by the code
public static double binomial(int N, int k, double p)
{
 if ((N == 0) || (k < 0)) return 1.0;
 return (1.0 - p)*binomial(N-1, k) + p*binomial(N-1, k-1);
}
to compute binomial(100, 50). Develop a better implementation that is based on saving computed values in an array.

Answer:
1.1.27 - Binomial distribution

For binomial(100, 50, 0.25) the estimate is around 5 billion calls.


Question:
Filtering. Which of the following require saving all the values from standard input (in an array, say), and which could be implemented as a filter using only a fixed number of variables and arrays of fixed size (not dependent on N)? For each, the input comes from standard input and consists of N real numbers between 0 and 1.
- Print the maximum and minimum numbers.
- Print the median of the numbers.
- Print the k th smallest value, for k less than 100.
- Print the sum of the squares of the numbers.
- Print the average of the N numbers.
- Print the percentage of numbers greater than the average.
- Print the N numbers in increasing order.
- Print the N numbers in random order.

Answer:
1.1.34 - Filtering

Print the maximum and minimum numbers -> Could be implemented as a filter
Print the median of the numbers -> Requires saving all values
Print the Kth smallest value, for K less than 100 -> Could be implemented as a filter with an array of size K
Print the sum of the squares of the numbers -> Could be implemented as a filter
Print the average of the N numbers -> Could be implemented as a filter
Print the percentage of numbers greater than the average -> Requires saving all values
Print the N numbers in increasing order -> Requires saving all values
Print the N numbers in random order -> Requires saving all values

Thanks to imyuewu (https://github.com/imyuewu) for suggesting a correction for the Kth smallest value case.
https://github.com/reneargento/algorithms-sedgewick-wayne/issues/175


Question:
Dice simulation. The following code computes the exact probability distribution for the sum of two dice:
int SIDES = 6;
double[] dist = new double[2*SIDES+1];
for (int i = 1; i <= SIDES; i++)
 for (int j = 1; j <= SIDES; j++)
 dist[i+j] += 1.0;
for (int k = 2; k <= 2*SIDES; k++)
 dist[k] /= 36.0;
The value dist[i] is the probability that the dice sum to k. Run experiments to validate this calculation simulating N dice throws, keeping track of the frequencies of occurrence of each value when you compute the sum of two random integers between 1 and 6. How large does N have to be before your empirical results match the exact results to three decimal places?

Answer:
1.1.35 - Dice simulation

N has to be 6.000.000 before my empirical results match the exact results to three decimal places.


Question: Binary search versus brute-force search. Write a program BruteForceSearch that uses the brute-force search method given on page 48 and compare its running time on your computer with that of BinarySearch for largeW.txt and largeT.txt.

Answer:
1.1.38 - Binary search versus brute-force search

largeW.txt results:

Bruteforce: 760274
Duration: 9705800 nanoseconds.
BinarySearch: 760274
Duration: 112000 nanoseconds.

largeT.txt results:

Bruteforce: 7328283
Duration: 1325191800 nanoseconds.
BinarySearch: 7328279
Duration: 158600 nanoseconds.

For testing:
https://algs4.cs.princeton.edu/11model/tinyW.txt
https://algs4.cs.princeton.edu/11model/tinyT.txt
https://algs4.cs.princeton.edu/11model/largeW.txt
https://algs4.cs.princeton.edu/11model/largeT.txt


Question: Write a Point2D client that takes an integer value N from the command line, generates N random points in the unit square, and computes the distance separating the closest pair of points.

Answer:
1.1.1
a) 7
b) 200.0000002
c) true


Question: Write an Interval1D client that takes an int value N as command-line argument, reads N intervals (each defined by a pair of double values) from standard input, and prints all pairs that intersect.

Answer:
1.1.2
a) 1.618 -> double
b) 10.0 -> double
c) true -> boolean
d) 33 -> String


Question:
What does the following code fragment print?
String string1 = "hello";
String string2 = string1;
string1 = "world";
StdOut.println(string1);
StdOut.println(string2);

Answer:
1.1.4
a) No such keyword as "then" in Java language
b) Missing Parentheses on if conditional
c) Nothing wrong
d) Missing semicolon after the "then" clause


Question: A string s is a circular rotation of a string t if it matches when the characters are circularly shifted by any number of positions; e.g., ACTGACG is a circular shift of TGACGAC, and vice versa. Detecting this condition is important in the study of genomic sequences. Write a program that checks whether two given strings s and t are circular shifts of one another. Hint: The solution is a one-liner with indexOf(), length(), and string concatenation.

Answer:
1.1.6

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610


Question:
What does the following recursive function return?
public static String mystery(String s)
{
 int N = s.length();
 if (N <= 1) return s;
 String a = s.substring(0, N/2);
 String b = s.substring(N/2, N);
 return mystery(b) + mystery(a);
}

Answer:
1.1.7
a) 3.00009
b) 499500
c) 10000


Question:
Suppose that a[] and b[] are each integer arrays consisting of millions of integers. What does the follow code do? Is it reasonably efficient?
int[] t = a; a = b; b = t;

Answer:
1.1.8
a) b -> converts the char "b" to String and prints it
b) 197 -> sums the char codes of "b" and "c", converts to String and prints it
c) e -> sums the char code of "a" with 4, converts it to char and prints it


Question: Develop a class VisualCounter that allows both increment and decrement operations. Take two arguments N and max in the constructor, where N specifies the maximum number of operations and max specifies the maximum absolute value for the counter. As a side effect, create a plot showing the value of the counter each time its tally changes.

Answer:
1.1.10
The array was not initialized and will generate a compile-time error.


Question: Add a method dayOfTheWeek() to SmartDate that returns a String value Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, or Sunday, giving the appropriate day of the week for the date. You may assume that the date is in the 21st century.

Answer:
1.1.12

0
1
2
3
4
4
3
2
1
0


Question:
Rational numbers. Implement an immutable data type Rational for rational numbers that supports addition, subtraction, multiplication, and division.
public class Rational
Rational(int numerator, int denominator)
Rational plus(Rational b) // sum of this number and b
Rational minus(Rational b) // difference of this number and b
Rational times(Rational b) // product of this number and b
Rational divides(Rational b) // quotient of this number and b
boolean equals(Rational that) // is this number equal to that ?
String toString() // string representation
You do not have to worry about testing for overflow (see Exercise 1.2.17), but use as instance variables two long values that represent the numerator and denominator to limit the possibility of overflow. Use Euclid’s algorithm (see page 4) to ensure that the numerator and denominator never have any common factors. Include a test client that exercises all of your methods.

Answer:
1.1.16

311361142246


Question: Robust implementation of rational numbers. Use assertions to develop an implementation of Rational (see Exercise 1.2.16) that is immune to overflow.

Answer:
1.1.17
The function never stops because it keeps calling itself on the first line, until a StackOverflowError occurs.


Question:
Variance for accumulator. Validate that the following code, which adds the methods var() and stddev() to Accumulator, computes both the mean and variance of the numbers presented as arguments to addDataValue():
public class Accumulator
{
 private double m;
 private double s;
 private int N;
 public void addDataValue(double x)
 {
 N++;
 s = s + 1.0 * (N-1) / N * (x - m) * (x - m);
 m = m + (x - m) / N;
 }
 public double mean()
 { return m; }
 public double var()
 { return s/(N - 1); }
 public double stddev()
 { return Math.sqrt(this.var()); }
}
This implementation is less susceptible to roundoff error than the straightforward implementation based on saving the sum of the squares of the numbers.

Answer:
1.1.18

mystery(2,25) is equal to 50
mystery(3,11) is equal to 33
mystery(a,b) computes a * b

mystery2(2,25) is equal to 33554432
mystery2(3,11) is equal to 177147
mystery2(a,b) computes a^b


Question:
Parsing. Develop the parse constructors for your Date and Transaction implementations of Exercise 1.2.13 that take a single String argument to specify the initialization values, using the formats given in the table below.
| type        | format                                     | example                |
|-------------|--------------------------------------------|------------------------|
| Date        | integers separated by slashes              | 5/22/1939              |
| Transaction | customer, date, and amount, separated by whitespace | Turing 5/22/1939 11.99 |

Answer:
1.1.19

The largest value of N that takes less than 1 hour to compute is 51.


Question: Add a method isFull() to FixedCapacityStackOfStrings.

Answer:
1.1.1
a) 7
b) 200.0000002
c) true


Question:
Give the output printed by java Stack for the input
it was - the best - of times - - - it was - the - -

Answer:
1.1.2
a) 1.618 -> double
b) 10.0 -> double
c) true -> boolean
d) 33 -> String


Question: Write a stack client Parentheses that reads in a text stream from standard input and uses a stack to determine whether its parentheses are properly balanced. For example, your program should print true for [()]{}{[()()]()} and false for [(]).

Answer:
1.1.4
a) No such keyword as "then" in Java language
b) Missing Parentheses on if conditional
c) Nothing wrong
d) Missing semicolon after the "then" clause


Question:
What does the following code fragment do to the queue q?
Stack<String> stack = new Stack<String>();
while (!q.isEmpty())
 stack.push(q.dequeue());
while (!stack.isEmpty())
 q.enqueue(stack.pop());

Answer:
1.1.6

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610


Question: Add a method peek() to Stack that returns the most recently inserted item on the stack (without popping it).

Answer:
1.1.7
a) 3.00009
b) 499500
c) 10000


Question:
Give the contents and size of the array for DoublingStackOfStrings with the input
it was - the best - of times - - - it was - the - -

Answer:
1.1.8
a) b -> converts the char "b" to String and prints it
b) 197 -> sums the char codes of "b" and "c", converts to String and prints it
c) e -> sums the char code of "a" with 4, converts it to char and prints it


Question: Write a filter InfixToPostfix that converts an arithmetic expression from infix to postfix.

Answer:
1.1.10
The array was not initialized and will generate a compile-time error.


Question: Write an iterable Stack client that has a static method copy() that takes a stack of strings as argument and returns a copy of the stack. Note: This ability is a prime example of the value of having an iterator, because it allows development of such functionality without changing the basic API.

Answer:
1.1.12

0
1
2
3
4
4
3
2
1
0


Question: Using readInts() on page 126 as a model, write a static method readDates() for Date that reads dates from standard input in the format specified in the table on page 119 and returns an array containing them.

Answer:
1.1.16

311361142246


Question: Do Exercise 1.3.16 for Transaction.

Answer:
1.1.17
The function never stops because it keeps calling itself on the first line, until a StackOverflowError occurs.


Question:
Suppose x is a linked-list node and not the last node on the list. What is the effect of the following code fragment?
x.next = x.next.next;

Answer:
1.1.18

mystery(2,25) is equal to 50
mystery(3,11) is equal to 33
mystery(a,b) computes a * b

mystery2(2,25) is equal to 33554432
mystery2(3,11) is equal to 177147
mystery2(a,b) computes a^b


Question: Give a code fragment that removes the last node in a linked list whose first node is first.

Answer:
1.1.19

The largest value of N that takes less than 1 hour to compute is 51.


Question: Write a method insertAfter() that takes two linked-list Node arguments and inserts the second after the first on its list (and does nothing if either argument is null).

Answer:
1.1.25

For all N E NaturalNumbers and for all nonnegative integers a <= N and b <= N, the Euclidean algorithm computes the greatest common divisor of a and b.

Proving that gcd(a, b) = gcd(b, a % b)

gcd(20,5) = gcd(5,0)

gcd(20,5) is 5
gcd(5,0) is also 5

http://math.stackexchange.com/questions/1274515/prove-that-euclids-algorithm-computes-the-gcd-of-any-pair-of-nonnegative-intege

https://www.whitman.edu/mathematics/higher_math_online/section03.03.html


Question: Write a method max() that takes a reference to the first node in a linked list as argument and returns the value of the maximum key in the list. Assume that all keys are positive integers, and return 0 if the list is empty.

Answer:
1.1.27 - Binomial distribution

For binomial(100, 50, 0.25) the estimate is around 5 billion calls.


Question:
Random bag. A random bag stores a collection of items and supports the following API:
public class RandomBag<Item> implements Iterable<Item>
RandomBag() // create an empty random bag
boolean isEmpty() // is the bag empty?
int size() // number of items in the bag
void add(Item item) // add an item
Write a class RandomBag that implements this API. Note that this API is the same as for Bag, except for the adjective random, which indicates that the iteration should provide the items in random order (all N! permutations equally likely, for each iterator). Hint: Put the items in an array and randomize their order in the iterator’s constructor.

Answer:
1.1.34 - Filtering

Print the maximum and minimum numbers -> Could be implemented as a filter
Print the median of the numbers -> Requires saving all values
Print the Kth smallest value, for K less than 100 -> Could be implemented as a filter with an array of size K
Print the sum of the squares of the numbers -> Could be implemented as a filter
Print the average of the N numbers -> Could be implemented as a filter
Print the percentage of numbers greater than the average -> Requires saving all values
Print the N numbers in increasing order -> Requires saving all values
Print the N numbers in random order -> Requires saving all values

Thanks to imyuewu (https://github.com/imyuewu) for suggesting a correction for the Kth smallest value case.
https://github.com/reneargento/algorithms-sedgewick-wayne/issues/175


Question:
Random queue. A random queue stores a collection of items and supports the following API:
public class RandomQueue<Item>
RandomQueue() // create an empty random queue
boolean isEmpty() // is the queue empty?
void enqueue(Item item) // add an item
Item dequeue() // remove and return a random item (sample without replacement)
Item sample() // return a random item, but do not remove (sample with replacement)
Write a class RandomQueue that implements this API. Hint: Use an array representation (with resizing). To remove an item, swap one at a random position (indexed 0 through N-1) with the one at the last position (index N-1). Then delete and return the last object, as in ResizingArrayStack. Write a client that deals bridge hands (13 cards each) using RandomQueue<Card>.

Answer:
1.1.35 - Dice simulation

N has to be 6.000.000 before my empirical results match the exact results to three decimal places.


Question:
Delete kth element. Implement a class that supports the following API:
public class GeneralizedQueue<Item>
GeneralizedQueue() // create an empty queue
boolean isEmpty() // is the queue empty?
void insert(Item x) // add an item
Item delete(int k) // delete and return the kth least recently inserted item
First, develop an implementation that uses an array implementation, and then develop one that uses a linked-list implementation. Note: the algorithms and data structures that we introduce in Chapter 3 make it possible to develop an implementation that can guarantee that both insert() and delete() take time proportional to the logarithm of the number of items in the queue—see Exercise 3.5.27.

Answer:
1.1.38 - Binary search versus brute-force search

largeW.txt results:

Bruteforce: 760274
Duration: 9705800 nanoseconds.
BinarySearch: 760274
Duration: 112000 nanoseconds.

largeT.txt results:

Bruteforce: 7328283
Duration: 1325191800 nanoseconds.
BinarySearch: 7328279
Duration: 158600 nanoseconds.

For testing:
https://algs4.cs.princeton.edu/11model/tinyW.txt
https://algs4.cs.princeton.edu/11model/tinyT.txt
https://algs4.cs.princeton.edu/11model/largeW.txt
https://algs4.cs.princeton.edu/11model/largeT.txt


Question: Forbidden triple for stack generability. Prove that a permutation can be generated by a stack (as in the previous question) if and only if it has no forbidden triple (a, b, c) such that a < b < c with c first, a second, and b third (possibly with other intervening integers between c and a and between a and b).

Answer:
1.3.46 - Forbidden triple for stack generability
Suppose that there is a forbidden triple (a,b,c). Item "c" is popped before "a" and "b", but "a" and "b" are pushed before "c".
Thus, when "c" is pushed, both "a" and "b" are on the stack. Therefore, "a" cannot be popped before "b".

When pushing items in the order 0, 1, ..., N-1, all items are above smaller items on the stack because they are pushed after smaller items.
If a < b, "a" cannot be above "b" on the stack. Therefore, a permutation would not exist when a forbidden triple exists.


Question: Show that the number of different triples that can be chosen from N items is precisely N(N-1)(N-2)/6. Hint: Use mathematical induction.

Answer:
1.1.1
a) 7
b) 200.0000002
c) true


Question: Modify ThreeSum to work properly even when the int values are so large that adding two of them might cause overflow.

Answer:
1.1.2
a) 1.618 -> double
b) 10.0 -> double
c) true -> boolean
d) 33 -> String


Question: Develop a table like the one on page 181 for TwoSum.

Answer:
1.1.4
a) No such keyword as "then" in Java language
b) Missing Parentheses on if conditional
c) Nothing wrong
d) Missing semicolon after the "then" clause


Question:
Give the order of growth (as a function of N) of the running times of each of the following code fragments:
a. int sum = 0;
 for (int n = N; n > 0; n /= 2)
 for(int i = 0; i < n; i++)
 sum++;
b. int sum = 0;
 for (int i = 1; i < N; i *= 2)
 for (int j = 0; j < i; j++)
 sum++;
c. int sum = 0;
 for (int i = 1; i < N; i *= 2)
 for (int j = 0; j < N; j++)
 sum++;

Answer:
1.1.6

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610


Question: Analyze ThreeSum under a cost model that counts arithmetic operations (and comparisons) involving the input numbers.

Answer:
1.1.7
a) 3.00009
b) 499500
c) 10000


Question: Write a program to determine the number pairs of values in an input file that are equal. If your first try is quadratic, think again and use Arrays.sort() to develop a linearithmic solution.

Answer:
1.1.8
a) b -> converts the char "b" to String and prints it
b) 197 -> sums the char codes of "b" and "c", converts to String and prints it
c) e -> sums the char code of "a" with 4, converts it to char and prints it


Question: Modify binary search so that it always returns the element with the smallest index that matches the search element (and still guarantees logarithmic running time).

Answer:
1.1.10
The array was not initialized and will generate a compile-time error.


Question: Write a program that, given two sorted arrays of N int values, prints all elements that appear in both arrays, in sorted order. The running time of your program should be proportional to N in the worst case.

Answer:
1.1.12

0
1
2
3
4
4
3
2
1
0


Question: Closest pair (in one dimension). Write a program that, given an array a[] of N double values, finds a closest pair: two values whose difference is no greater than the difference of any other pair (in absolute value). The running time of your program should be linearithmic in the worst case.

Answer:
1.1.16

311361142246


Question: Farthest pair (in one dimension). Write a program that, given an array a[] of N double values, finds a farthest pair: two values whose difference is no smaller than the difference of any other pair (in absolute value). The running time of your program should be linear in the worst case.

Answer:
1.1.17
The function never stops because it keeps calling itself on the first line, until a StackOverflowError occurs.


Question: Local minimum of an array. Write a program that, given an array a[] of N distinct integers, finds a local minimum: an index i such that a[i-1] < a[i] < a[i+1]. Your program should use ~2lg N compares in the worst case.

Answer:
1.1.18

mystery(2,25) is equal to 50
mystery(3,11) is equal to 33
mystery(a,b) computes a * b

mystery2(2,25) is equal to 33554432
mystery2(3,11) is equal to 177147
mystery2(a,b) computes a^b


Question: Local minimum of a matrix. Given an N-by-N array a[] of N^2 distinct integers, design an algorithm that runs in time proportional to N to find a local minimum: a pair of indices i and j such that a[i][j] < a[i+1][j], a[i][j] < a[i][j+1], a[i][j] < a[i-1][j], and a[i][j] < a[i][j-1]. The running time of your program should be proportional to N in the worst case.

Answer:
1.1.19

The largest value of N that takes less than 1 hour to compute is 51.


Question: Throwing two eggs from a building. Consider the previous question, but now suppose you only have two eggs, and your cost model is the number of throws. Devise a strategy to determine F such that the number of throws is at most 2√N, then find a way to reduce the cost to ~c√F. This is analogous to a situation where search hits (egg intact) are much cheaper than misses (egg broken).

Answer:
1.1.25

For all N E NaturalNumbers and for all nonnegative integers a <= N and b <= N, the Euclidean algorithm computes the greatest common divisor of a and b.

Proving that gcd(a, b) = gcd(b, a % b)

gcd(20,5) = gcd(5,0)

gcd(20,5) is 5
gcd(5,0) is also 5

http://math.stackexchange.com/questions/1274515/prove-that-euclids-algorithm-computes-the-gcd-of-any-pair-of-nonnegative-intege

https://www.whitman.edu/mathematics/higher_math_online/section03.03.html


Question: Queue with two stacks. Implement a queue with two stacks so that each queue operation takes a constant amortized number of stack operations. Hint: If you push elements onto a stack and then pop them all, they appear in reverse order. If you repeat this process, they’re now back in order.

Answer:
1.1.27 - Binomial distribution

For binomial(100, 50, 0.25) the estimate is around 5 billion calls.


Question: Hot or cold. Your goal is to guess a secret integer between 1 and N. You repeatedly guess integers between 1 and N. After each guess you learn if your guess equals the secret integer (and the game stops). Otherwise, you learn if the guess is hotter (closer to) or colder (farther from) the secret number than your previous guess. Design an algorithm that finds the secret number in at most ~2 lg N guesses. Then design an algorithm that finds the secret number in at most ~ 1 lg N guesses.

Answer:
1.1.34 - Filtering

Print the maximum and minimum numbers -> Could be implemented as a filter
Print the median of the numbers -> Requires saving all values
Print the Kth smallest value, for K less than 100 -> Could be implemented as a filter with an array of size K
Print the sum of the squares of the numbers -> Could be implemented as a filter
Print the average of the N numbers -> Could be implemented as a filter
Print the percentage of numbers greater than the average -> Requires saving all values
Print the N numbers in increasing order -> Requires saving all values
Print the N numbers in random order -> Requires saving all values

Thanks to imyuewu (https://github.com/imyuewu) for suggesting a correction for the Kth smallest value case.
https://github.com/reneargento/algorithms-sedgewick-wayne/issues/175


Question:
Time costs for pushdown stacks. Justify the entries in the table below, which shows typical time costs for various pushdown stack implementations, using a cost model that counts both data references (references to data pushed onto the stack, either an array reference or a reference to an object’s instance variable) and objects created.
| data structure   | item type | cost to push N int values | |
|------------------|-----------|---------------------------|----------------|
|                  |           | data references           | objects created |
| linked list      | int       | 2N                        | N              |
|                  | Integer   | 3N                        | 2N             |
| resizing array   | int       | ~5N                       | lg N           |
|                  | Integer   | ~5N                       | ~N             |

Answer:
1.1.35 - Dice simulation

N has to be 6.000.000 before my empirical results match the exact results to three decimal places.


Question:
Naive 3-sum implementation. Run experiments to evaluate the following implementation of the inner loop of ThreeSum:
for (int i = 0; i < N; i++)
 for (int j = 0; j < N; j++)
 for (int k = 0; k < N; k++)
 if (i < j && j < k)
 if (a[i] + a[j] + a[k] == 0)
 cnt++;
Do so by developing a version of DoublingTest that computes the ratio of the running times of this program and ThreeSum.

Answer:
1.1.38 - Binary search versus brute-force search

largeW.txt results:

Bruteforce: 760274
Duration: 9705800 nanoseconds.
BinarySearch: 760274
Duration: 112000 nanoseconds.

largeT.txt results:

Bruteforce: 7328283
Duration: 1325191800 nanoseconds.
BinarySearch: 7328279
Duration: 158600 nanoseconds.

For testing:
https://algs4.cs.princeton.edu/11model/tinyW.txt
https://algs4.cs.princeton.edu/11model/tinyT.txt
https://algs4.cs.princeton.edu/11model/largeW.txt
https://algs4.cs.princeton.edu/11model/largeT.txt


Question: Show the contents of the id[] array and the number of times the array is accessed for each input pair when you use quick-find for the sequence 9-0 3-4 5-8 7-2 2-1 5-7 0-3 4-2.

Answer:
1.1.1
a) 7
b) 200.0000002
c) true


Question: Do Exercise 1.5.1, but use quick-union (page 224). In addition, draw the forest of trees represented by the id[] array after each input pair is processed.

Answer:
1.1.2
a) 1.618 -> double
b) 10.0 -> double
c) true -> boolean
d) 33 -> String


Question: Show the contents of the sz[] and id[] arrays and the number of array accesses for each input pair corresponding to the weighted quick-union examples in the text (both the reference input and the worst-case input).

Answer:
1.1.4
a) No such keyword as "then" in Java language
b) Missing Parentheses on if conditional
c) Nothing wrong
d) Missing semicolon after the "then" clause


Question: Repeat Exercise 1.5.5 for weighted quick-union.

Answer:
1.1.6

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610


Question: Develop classes QuickUnionUF and QuickFindUF that implement quick-union and quick-find, respectively.

Answer:
1.1.7
a) 3.00009
b) 499500
c) 10000


Question:
Give a counterexample that shows why this intuitive implementation of union() for quick-find is not correct:
public void union(int p, int q)
{
 if (connected(p, q)) return;
 // Rename p’s component to q’s name.
 for (int i = 0; i < id.length; i++)
 if (id[i] == id[p]) id[i] = id[q];
 count--;
}

Answer:
1.1.8
a) b -> converts the char "b" to String and prints it
b) 197 -> sums the char codes of "b" and "c", converts to String and prints it
c) e -> sums the char code of "a" with 4, converts it to char and prints it


Question: In the weighted quick-union algorithm, suppose that we set id[find(p)] to q instead of to id[find(q)]. Would the resulting algorithm be correct?

Answer:
1.1.10
The array was not initialized and will generate a compile-time error.


Question: Quick-union with path compression. Modify quick-union (page 224) to include path compression, by adding a loop to union() that links every site on the paths from p and q to the roots of their trees to the root of the new tree. Give a sequence of input pairs that causes this method to produce a path of length 4. Note: The amortized cost per operation for this algorithm is known to be logarithmic.

Answer:
1.1.12

0
1
2
3
4
4
3
2
1
0


Question: Amortized costs plots. Instrument your implementations from Exercise 1.5.7 to make amortized costs plots like those in the text.

Answer:
1.1.16

311361142246


Question: Random connections. Develop a UF client ErdosRenyi that takes an integer value N from the command line, generates random pairs of integers between 0 and N-1, calling connected() to determine if they are connected and then union() if not (as in our development client), looping until all sites are connected, and printing the number of connections generated. Package your program as a static method count() that takes N as argument and returns the number of connections and a main() that takes N from the command line, calls count(), and prints the returned value.

Answer:
1.1.17
The function never stops because it keeps calling itself on the first line, until a StackOverflowError occurs.


Question:
Random grid generator. Write a program RandomGrid that takes an int value N from the command line, generates all the connections in an N-by-N grid, puts them in random order, randomly orients them (so that p q and q p are equally likely to occur), and prints the result to standard output. To randomly order the connections, use a RandomBag (see Exercise 1.3.34 on page 167). To encapsulate p and q in a single object, use the Connection nested class shown below. Package your program as two static methods: generate(), which takes N as argument and returns an array of connections, and main(), which takes N from the command line, calls generate(), and iterates through the returned array to print the connections.
private class Connection
{
 int p;
 int q;
 public Connection(int p, int q)
 { this.p = p; this.q = q; }
}

Answer:
1.1.18

mystery(2,25) is equal to 50
mystery(3,11) is equal to 33
mystery(a,b) computes a * b

mystery2(2,25) is equal to 33554432
mystery2(3,11) is equal to 177147
mystery2(a,b) computes a^b


Question: Animation. Write a RandomGrid client (see Exercise 1.5.18) that uses UnionFind as in our development client to check connectivity and uses StdDraw to draw the connections as they are processed.

Answer:
1.1.19

The largest value of N that takes less than 1 hour to compute is 51.


Question: Doubling test for random grids. Develop a performance-testing client that takes an int value T from the command line and performs T trials of the following experiment: Use your client from Exercise 1.5.18 to generate the connections in an N-by-N square grid, randomly oriented and in random order, then use UnionFind to determine connectivity as in our development client, looping until all sites are connected. For each N, print the value of N, the average number of connections processed, and the ratio of the running time to the previous. Use your program to validate the hypotheses in the text that the running times for quick-find and quick-union are quadratic and weighted quick-union is near-linear. Note: As N doubles, the number of sites in the grid increases by a factor of 4, so expect a doubling factor of 16 for quadratic and 4 for linear.

Answer:
1.1.25

For all N E NaturalNumbers and for all nonnegative integers a <= N and b <= N, the Euclidean algorithm computes the greatest common divisor of a and b.

Proving that gcd(a, b) = gcd(b, a % b)

gcd(20,5) = gcd(5,0)

gcd(20,5) is 5
gcd(5,0) is also 5

http://math.stackexchange.com/questions/1274515/prove-that-euclids-algorithm-computes-the-gcd-of-any-pair-of-nonnegative-intege

https://www.whitman.edu/mathematics/higher_math_online/section03.03.html


Question: Show, in the style of the example trace with Algorithm 2.1, how selection sort sorts the array E A S Y Q U E S T I O N.

Answer:
2.1.1
		a[]
i  min  0 1 2 3 4 5 6 7 8 9 10 11
	E A S Y Q U E S T I  O  N
0    1  E A S Y Q U E S T I  O  N
1    1  A E S Y Q U E S T I  O  N
2    6  A E S Y Q U E S T I  O  N
3    9  A E E Y Q U S S T I  O  N
4   11  A E E I Q U S S T Y  O  N
5   10  A E E I N U S S T Y  O  Q
6   11  A E E I N O S S T Y  U  Q
7    7  A E E I N O Q S T Y  U  S
8   11  A E E I N O Q S T Y  U  S
9   11  A E E I N O Q S S Y  U  T
10  10  A E E I N O Q S S T  U  Y
11  11  A E E I N O Q S S T  U  Y
	A E E I N O Q S S T  U  Y


Question: What is the maximum number of exchanges involving any particular element during selection sort? What is the average number of exchanges involving an element?

Answer:
2.1.2
The maximum number of exchanges involving any particular item during selection sort is N - 1.
This happens when the first item has the highest value in the unsorted array and the other values are sorted.
For example, in the array 4 1 2 3, the element 4 will be swapped N - 1 times.
The average number of exchanges involving an item is exactly 2, because there are exactly N exchanges and N items (and each exchange involves two items).

Reference: https://algs4.cs.princeton.edu/21elementary/


Question: Give an example of an array of N items that maximizes the number of times the test a[j] < a[min] fails (and, therefore, min gets updated) during the operation of selection sort (Algorithm 2.1).

Answer:
2.1.3
Array: H G F E D C B A

Thanks to QiotoF (https://github.com/QiotoF) for mentioning a better array solution for this exercise
https://github.com/reneargento/algorithms-sedgewick-wayne/issues/76


Question: Show, in the style of the example trace with Algorithm 2.2, how insertion sort sorts the array E A S Y Q U E S T I O N.

Answer:
2.1.4
		a[]
i    j  0 1 2 3 4 5 6 7 8 9 10 11
	E A S Y Q U E S T I  O  N
0    0  E A S Y Q U E S T I  O  N
1    0  A E S Y Q U E S T I  O  N
2    2  A E S Y Q U E S T I  O  N
3    3  A E S Y Q U E S T I  O  N
4    2  A E Q S Y U E S T I  O  N
5    4  A E Q S U Y E S T I  O  N
6    2  A E E Q S U Y S T I  O  N
7    5  A E E Q S S U Y T I  O  N
8    6  A E E Q S S T U Y I  O  N
9    3  A E E I Q S S T U Y  O  N
10   4  A E E I O Q S S T U  Y  N
11   4  A E E I N O Q S S T  U  Y
	A E E I N O Q S S T  U  Y


Question: For each of the two conditions in the inner for loop in insertion sort (Algorithm 2.2), describe an array of N items where that condition is always false when the loop terminates.

Answer:
2.1.5

Condition 1: j > 0 -> When the array is reverse ordered
Z Q K D C B A

Condition 2: less(a[j], a[j - 1]) -> When the array is ordered
A B C D E F G


Question: Which method runs faster for an array with all keys identical, selection sort or insertion sort?

Answer:
2.1.6

Insertion sort because it will only make one comparison with the previous element (per element) and won't exchange any elements,
running in linear time. Selection sort will exchange each element with itself and will run in quadratic time.

Thanks to glucu (https://github.com/glucu) for correcting the number of exchanges done in selection sort.