This public repository
contains the Java source code
for the algorithms and clients in the textbook
Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
The official version at https://github.com/kevin-wayne/algs4
is actively maintained and updated by the authors.
The programs are organized in the package edu.princeton.cs.algs4.
If you need only the class files (and not the source code), you can use
algs4.jar instead.
* This symbol table implementation uses internally an * AVL tree (Georgy * Adelson-Velsky and Evgenii Landis' tree) which is a self-balancing BST. * In an AVL tree, the heights of the two child subtrees of any * node differ by at most one; if at any time they differ by more than one, * rebalancing is done to restore this property. *
* This implementation requires that the key type implements the
* {@code Comparable} interface and calls the {@code compareTo()} and
* method to compare two keys. It does not call either {@code equals()} or
* {@code hashCode()}. The put, get, contains,
* delete, minimum, maximum, ceiling, and
* floor operations each take logarithmic time in the worst case. The
* size, and is-empty operations take constant time.
* Construction also takes constant time.
*
* For other implementations of the same API, see {@link ST}, {@link BinarySearchST},
* {@link SequentialSearchST}, {@link BST}, {@link RedBlackBST},
* {@link SeparateChainingHashST}, and {@link LinearProbingHashST}.
*
* @author Marcelo Silva
*/
public class AVLTreeST
* This implementation uses a one-pass algorithm that is less susceptible
* to floating-point roundoff error than the more straightforward
* implementation based on saving the sum of the squares of the numbers.
* This technique is due to
* B. P. Welford.
* Each operation takes constant time in the worst case.
* The amount of memory is constant - the data values are not stored.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Accumulator {
private int n = 0; // number of data values
private double sum = 0.0; // sample variance * (n-1)
private double mu = 0.0; // sample mean
/**
* Initializes an accumulator.
*/
public Accumulator() {
}
/**
* Adds the specified data value to the accumulator.
* @param x the data value
*/
public void addDataValue(double x) {
n++;
double delta = x - mu;
mu += delta / n;
sum += ((double) (n - 1) / n) * delta * delta;
}
/**
* Returns the mean of the data values.
* @return the mean of the data values
*/
public double mean() {
return mu;
}
/**
* Returns the sample variance of the data values.
* @return the sample variance of the data values
*/
public double var() {
if (n <= 1) return Double.NaN;
return sum / (n - 1);
}
/**
* Returns the sample standard deviation of the data values.
* @return the sample standard deviation of the data values
*/
public double stddev() {
return Math.sqrt(this.var());
}
/**
* Returns the number of data values.
* @return the number of data values
*/
public int count() {
return n;
}
/**
* Returns a string representation of this accumulator.
* @return a string representation of this accumulator
*/
public String toString() {
return "n = " + n + ", mean = " + mean() + ", stddev = " + stddev();
}
/**
* Unit tests the {@code Accumulator} data type.
* Reads in a stream of real number from standard input;
* adds them to the accumulator; and prints the mean,
* sample standard deviation, and sample variance to standard
* output.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
Accumulator stats = new Accumulator();
while (!StdIn.isEmpty()) {
double x = StdIn.readDouble();
stats.addDataValue(x);
}
StdOut.printf("n = %d\n", stats.count());
StdOut.printf("mean = %.5f\n", stats.mean());
StdOut.printf("stddev = %.5f\n", stats.stddev());
StdOut.printf("var = %.5f\n", stats.var());
StdOut.println(stats);
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/AcyclicLP.java
================================================
/******************************************************************************
* 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
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* 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
* 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 shortest 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 AcyclicSP {
private double[] distTo; // distTo[v] = distance of shortest s->v path
private DirectedEdge[] edgeTo; // edgeTo[v] = last edge on shortest s->v path
/**
* Computes a shortest 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 AcyclicSP(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.POSITIVE_INFINITY;
distTo[s] = 0.0;
// visit 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
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 shortest path from the source vertex {@code s} to vertex {@code v}.
* @param v the destination vertex
* @return the length of a shortest path from the source vertex {@code s} to vertex {@code v};
* {@code Double.POSITIVE_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.POSITIVE_INFINITY;
}
/**
* Returns a shortest path from the source vertex {@code s} to vertex {@code v}.
* @param v the destination vertex
* @return a shortest 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
* This implementation uses an adjacency-matrix representation.
* All operations take constant time (in the worst case) except
* iterating over the edges incident from a given vertex, which takes
* time proportional to V.
*
* 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 AdjMatrixEdgeWeightedDigraph {
private static final String NEWLINE = System.getProperty("line.separator");
private final int V;
private int E;
private DirectedEdge[][] adj;
/**
* 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 AdjMatrixEdgeWeightedDigraph(int V) {
if (V < 0) throw new IllegalArgumentException("number of vertices must be non-negative");
this.V = V;
this.E = 0;
this.adj = new DirectedEdge[V][V];
}
/**
* 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 AdjMatrixEdgeWeightedDigraph(int V, int E) {
this(V);
if (E < 0) throw new IllegalArgumentException("number of edges must be non-negative");
if (E > V*V) throw new IllegalArgumentException("too many edges");
// can be inefficient
while (this.E != E) {
int v = StdRandom.uniformInt(V);
int w = StdRandom.uniformInt(V);
double weight = 0.01 * StdRandom.uniformInt(0, 100);
addEdge(new DirectedEdge(v, w, weight));
}
}
/**
* Returns the number of vertices in the edge-weighted digraph.
* @return the number of vertices in the edge-weighted digraph
*/
public int V() {
return V;
}
/**
* Returns the number of edges in the edge-weighted digraph.
* @return the number of edges in the edge-weighted digraph
*/
public int E() {
return E;
}
/**
* Adds the directed edge {@code e} to the edge-weighted digraph (if there
* is not already an edge with the same endpoints).
* @param e the edge
*/
public void addEdge(DirectedEdge e) {
int v = e.from();
int w = e.to();
validateVertex(v);
validateVertex(w);
if (adj[v][w] == null) {
E++;
adj[v][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
* For additional documentation,
* see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class AllowFilter {
// Do not instantiate.
private AllowFilter() { }
public static void main(String[] args) {
SET
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Allowlist {
// Do not instantiate.
private Allowlist() { }
/**
* Reads in a sequence of integers from the allowlist file, specified as
* a command-line argument. Reads in integers from standard input and
* prints to standard output those integers that are not in the file.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
In in = new In(args[0]);
int[] white = in.readAllInts();
StaticSETofInts set = new StaticSETofInts(white);
// Read key, print if not in allowlist.
while (!StdIn.isEmpty()) {
int key = StdIn.readInt();
if (!set.contains(key))
StdOut.println(key);
}
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/Alphabet.java
================================================
/******************************************************************************
* Compilation: javac Alphabet.java
* Execution: java Alphabet
* Dependencies: StdOut.java
*
* A data type for alphabets, for use with string-processing code
* that must convert between an alphabet of size R and the integers
* 0 through R-1.
*
* Warning: supports only the basic multilingual plane (BMP), i.e,
* Unicode characters between U+0000 and U+FFFF.
*
******************************************************************************/
package edu.princeton.cs.algs4;
public class Alphabet {
/**
* The binary alphabet { 0, 1 }.
*/
public static final Alphabet BINARY = new Alphabet("01");
/**
* The octal alphabet { 0, 1, 2, 3, 4, 5, 6, 7 }.
*/
public static final Alphabet OCTAL = new Alphabet("01234567");
/**
* The decimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.
*/
public static final Alphabet DECIMAL = new Alphabet("0123456789");
/**
* The hexadecimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F }.
*/
public static final Alphabet HEXADECIMAL = new Alphabet("0123456789ABCDEF");
/**
* The DNA alphabet { A, C, T, G }.
*/
public static final Alphabet DNA = new Alphabet("ACGT");
/**
* The lowercase alphabet { a, b, c, ..., z }.
*/
public static final Alphabet LOWERCASE = new Alphabet("abcdefghijklmnopqrstuvwxyz");
/**
* The uppercase alphabet { A, B, C, ..., Z }.
*/
public static final Alphabet UPPERCASE = new Alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
/**
* The protein alphabet { A, C, D, E, F, G, H, I, K, L, M, N, P, Q, R, S, T, V, W, Y }.
*/
public static final Alphabet PROTEIN = new Alphabet("ACDEFGHIKLMNPQRSTVWY");
/**
* The base-64 alphabet (64 characters).
*/
public static final Alphabet BASE64 = new Alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
/**
* The ASCII alphabet (0-127).
*/
public static final Alphabet ASCII = new Alphabet(128);
/**
* The extended ASCII alphabet (0-255).
*/
public static final Alphabet EXTENDED_ASCII = new Alphabet(256);
/**
* The Unicode 16 alphabet (0-65,535).
*/
public static final Alphabet UNICODE16 = new Alphabet(65536);
private char[] alphabet; // the characters in the alphabet
private int[] inverse; // indices
private final int R; // the radix of the alphabet
/**
* Initializes a new alphabet from the given set of characters.
*
* @param alpha the set of characters
*/
public Alphabet(String alpha) {
// check that alphabet contains no duplicate chars
boolean[] unicode = new boolean[Character.MAX_VALUE];
for (int i = 0; i < alpha.length(); i++) {
char c = alpha.charAt(i);
if (unicode[c])
throw new IllegalArgumentException("Illegal alphabet: repeated character = '" + c + "'");
unicode[c] = true;
}
alphabet = alpha.toCharArray();
R = alpha.length();
inverse = new int[Character.MAX_VALUE];
for (int i = 0; i < inverse.length; i++)
inverse[i] = -1;
// can't use char since R can be as big as 65,536
for (int c = 0; c < R; c++)
inverse[alphabet[c]] = c;
}
/**
* Initializes a new alphabet using characters 0 through R-1.
*
* @param radix the number of characters in the alphabet (the radix R)
*/
private Alphabet(int radix) {
this.R = radix;
alphabet = new char[R];
inverse = new int[R];
// can't use char since R can be as big as 65,536
for (int i = 0; i < R; i++)
alphabet[i] = (char) i;
for (int i = 0; i < R; i++)
inverse[i] = i;
}
/**
* Initializes a new alphabet using characters 0 through 255.
*/
public Alphabet() {
this(256);
}
/**
* Returns true if the argument is a character in this alphabet.
*
* @param c the character
* @return {@code true} if {@code c} is a character in this alphabet;
* {@code false} otherwise
*/
public boolean contains(char c) {
return inverse[c] != -1;
}
/**
* Returns the number of characters in this alphabet (the radix).
*
* @return the number of characters in this alphabet
* @deprecated Replaced by {@link #radix()}.
*/
@Deprecated
public int R() {
return R;
}
/**
* Returns the number of characters in this alphabet (the radix).
*
* @return the number of characters in this alphabet
*/
public int radix() {
return R;
}
/**
* Returns the binary logarithm of the number of characters in this alphabet.
*
* @return the binary logarithm (rounded up) of the number of characters in this alphabet
*/
public int lgR() {
int lgR = 0;
for (int t = R-1; t >= 1; t /= 2)
lgR++;
return lgR;
}
/**
* Returns the index corresponding to the argument character.
*
* @param c the character
* @return the index corresponding to the character {@code c}
* @throws IllegalArgumentException unless {@code c} is a character in this alphabet
*/
public int toIndex(char c) {
if (c >= inverse.length || inverse[c] == -1) {
throw new IllegalArgumentException("Character " + c + " not in alphabet");
}
return inverse[c];
}
/**
* Returns the indices corresponding to the argument characters.
*
* @param s the characters
* @return the indices corresponding to the characters {@code s}
* @throws IllegalArgumentException unless every character in {@code s}
* is a character in this alphabet
*/
public int[] toIndices(String s) {
char[] source = s.toCharArray();
int[] target = new int[s.length()];
for (int i = 0; i < source.length; i++)
target[i] = toIndex(source[i]);
return target;
}
/**
* Returns the character corresponding to the argument index.
*
* @param index the index
* @return the character corresponding to the index {@code index}
* @throws IllegalArgumentException unless {@code 0 <= index < R}
*/
public char toChar(int index) {
if (index < 0 || index >= R) {
throw new IllegalArgumentException("index must be between 0 and " + R + ": " + index);
}
return alphabet[index];
}
/**
* Returns the characters corresponding to the argument indices.
*
* @param indices the indices
* @return the characters corresponding to the indices {@code indices}
* @throws IllegalArgumentException unless {@code 0 < indices[i] < R}
* for every {@code i}
*/
public String toChars(int[] indices) {
StringBuilder s = new StringBuilder(indices.length);
for (int i = 0; i < indices.length; i++)
s.append(toChar(indices[i]));
return s.toString();
}
/**
* Unit tests the {@code Alphabet} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int[] encoded1 = Alphabet.BASE64.toIndices("NowIsTheTimeForAllGoodMen");
String decoded1 = Alphabet.BASE64.toChars(encoded1);
StdOut.println(decoded1);
int[] encoded2 = Alphabet.DNA.toIndices("AACGAACGGTTTACCCCG");
String decoded2 = Alphabet.DNA.toChars(encoded2);
StdOut.println(decoded2);
int[] encoded3 = Alphabet.DECIMAL.toIndices("01234567890123456789");
String decoded3 = Alphabet.DECIMAL.toChars(encoded3);
StdOut.println(decoded3);
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/AmericanFlag.java
================================================
/******************************************************************************
* Compilation: javac AmericanFlag.java
* Execution: java AmericanFlag < input.txt
* java AmericanFlag int < input-non-negative-ints.txt
* Dependencies: StdIn.java StdOut.java Stack.java
* Data files: https://algs4.cs.princeton.edu/51radix/words3.txt
* https://algs4.cs.princeton.edu/51radix/shells.txt
*
* Sort an array of strings or integers in-place using American flag sort.
*
* % java AmericanFlag < shells.txt
* are
* by
* sea
* seashells
* seashells
* sells
* sells
* she
* she
* shells
* shore
* surely
* the
* the
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code AmericanFlag} class provides static methods for sorting an
* array of extended ASCII strings or integers in-place using
* American flag sort. This is a non-recursive implementation.
*
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne
* and
* Engineering Radix Sort by McIlroy and Bostic.
* For a version that uses only one auxiliary array, see {@link AmericanFlagX}.
*
* @author Robert Sedgewick
* @author Kevin Wayne
* @author Ivan Pesin
*/
public class AmericanFlag {
private static final int BITS_PER_BYTE = 8;
private static final int BITS_PER_INT = 32; // each Java int is 32 bits
private static final int R = 256; // extend ASCII alphabet size
private static final int CUTOFF = 15; // cutoff to insertion sort
// do not instantiate
private AmericanFlag() { }
// return dth character of s, -1 if d = length of string
private static int charAt(String s, int d) {
assert d >= 0 && d <= s.length();
if (d == s.length()) return -1;
return s.charAt(d);
}
/**
* Rearranges the array of extended ASCII strings in ascending order.
* This is an unstable sorting algorithm.
*
* @param a the array to be sorted
*/
public static void sort(String[] a) {
sort(a, 0, a.length - 1);
}
// sort from a[lo] to a[hi], starting at the dth character
public static void sort(String[] a, int lo, int hi) {
// one-time allocation of data structures
Stack
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne
* and
* Engineering Radix Sort by McIlroy and Bostic.
* For a version that uses two auxiliary arrays, see {@link AmericanFlag}.
*
* @author Ivan Pesin
*/
public class AmericanFlagX {
private static final int R = 256; // extend ASCII alphabet size
private static final int CUTOFF = 15; // cutoff to insertion sort
// do not instantiate
private AmericanFlagX() { }
// return dth character of s, -1 if d = length of string
private static int charAt(String s, int d) {
assert d >= 0 && d <= s.length();
if (d == s.length()) return -1;
return s.charAt(d);
}
/**
* Rearranges the array of extended ASCII strings in ascending order.
* This is an unstable in-place sorting algorithm.
*
* @param a the array to be sorted
*/
public static void sort(String[] a) {
sort(a, 0, a.length - 1);
}
// sort from a[lo] to a[hi], starting at the dth character
public static void sort(String[] a, int lo, int hi) {
// one-time allocation of data structures
Stack
* This implementation uses the Bellman-Ford algorithm to find a
* negative cycle in the complete digraph.
* The running time is proportional to V3 in the
* worst case, where V is the number of currencies.
*
* This code is guaranteed to find an arbitrage opportunity in a
* currency exchange table (or report that no such arbitrage
* opportunity exists) under the assumption that all arithmetic
* performed is without floating-point rounding error or arithmetic
* overflow. Since the code computes the logarithms of the edge weights,
* floating-point rounding error will be present, and it may fail on
* some pathological inputs.
*
* 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 Arbitrage {
// this class cannot be instantiated
private Arbitrage() { }
/**
* Reads the currency exchange table from standard input and
* prints an arbitrage opportunity to standard output (if one exists).
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// V currencies
int V = StdIn.readInt();
String[] name = new String[V];
// create complete network
EdgeWeightedDigraph G = new EdgeWeightedDigraph(V);
for (int v = 0; v < V; v++) {
name[v] = StdIn.readString();
for (int w = 0; w < V; w++) {
double rate = StdIn.readDouble();
DirectedEdge e = new DirectedEdge(v, w, -Math.log(rate));
G.addEdge(e);
}
}
// find negative cycle
BellmanFordSP spt = new BellmanFordSP(G, 0);
if (spt.hasNegativeCycle()) {
double stake = 1000.0;
for (DirectedEdge e : spt.negativeCycle()) {
StdOut.printf("%10.5f %s ", stake, name[e.from()]);
stake *= Math.exp(-e.weight());
StdOut.printf("= %10.5f %s\n", stake, name[e.to()]);
}
}
else {
StdOut.println("No arbitrage opportunity");
}
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/AssignmentProblem.java
================================================
/******************************************************************************
* Compilation: javac AssignmentProblem.java
* Execution: java AssignmentProblem n
* Dependencies: DijkstraSP.java DirectedEdge.java
*
* Solve an n-by-n assignment problem in n^3 log n time using the
* successive shortest path algorithm.
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code AssignmentProblem} class represents a data type for computing
* an optimal solution to an n-by-n assignment problem.
* The assignment problem is to find a minimum weight matching in an
* edge-weighted complete bipartite graph.
*
* The data type supplies methods for determining the optimal solution
* and the corresponding dual solution.
*
* This implementation uses the successive shortest paths algorithm.
* The order of growth of the running time in the worst case is
* O(n^3 log n) to solve an n-by-n
* instance.
*
* This computes correct results 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.
*
* For additional documentation, see
* Section 6.5
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class AssignmentProblem {
private static final double FLOATING_POINT_EPSILON = 1.0E-14;
private static final int UNMATCHED = -1;
private int n; // number of rows and columns
private double[][] weight; // the n-by-n cost matrix
private double minWeight; // minimum value of any weight
private double[] px; // px[i] = dual variable for row i
private double[] py; // py[j] = dual variable for col j
private int[] xy; // xy[i] = j means i-j is a match
private int[] yx; // yx[j] = i means i-j is a match
/**
* Determines an optimal solution to the assignment problem.
*
* @param weight the n-by-n matrix of weights
* @throws IllegalArgumentException unless all weights are nonnegative
* @throws IllegalArgumentException if {@code weight} is {@code null}
*/
public AssignmentProblem(double[][] weight) {
if (weight == null) throw new IllegalArgumentException("constructor argument is null");
n = weight.length;
this.weight = new double[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (Double.isNaN(weight[i][j]))
throw new IllegalArgumentException("weight " + i + "-" + j + " is NaN");
if (weight[i][j] < minWeight) minWeight = weight[i][j];
this.weight[i][j] = weight[i][j];
}
}
// dual variables
px = new double[n];
py = new double[n];
// initial matching is empty
xy = new int[n];
yx = new int[n];
for (int i = 0; i < n; i++)
xy[i] = UNMATCHED;
for (int j = 0; j < n; j++)
yx[j] = UNMATCHED;
// add n edges to matching
for (int k = 0; k < n; k++) {
assert isDualFeasible();
assert isComplementarySlack();
augment();
}
assert certifySolution();
}
// find shortest augmenting path and update
private void augment() {
// build residual graph
EdgeWeightedDigraph G = new EdgeWeightedDigraph(2*n+2);
int s = 2*n, t = 2*n+1;
for (int i = 0; i < n; i++) {
if (xy[i] == UNMATCHED)
G.addEdge(new DirectedEdge(s, i, 0.0));
}
for (int j = 0; j < n; j++) {
if (yx[j] == UNMATCHED)
G.addEdge(new DirectedEdge(n+j, t, py[j]));
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (xy[i] == j) G.addEdge(new DirectedEdge(n+j, i, 0.0));
else G.addEdge(new DirectedEdge(i, n+j, reducedCost(i, j)));
}
}
// compute shortest path from s to every other vertex
DijkstraSP spt = new DijkstraSP(G, s);
// augment along alternating path
for (DirectedEdge e : spt.pathTo(t)) {
int i = e.from(), j = e.to() - n;
if (i < n) {
xy[i] = j;
yx[j] = i;
}
}
// update dual variables
for (int i = 0; i < n; i++)
px[i] += spt.distTo(i);
for (int j = 0; j < n; j++)
py[j] += spt.distTo(n+j);
}
// reduced cost of i-j
// (subtracting off minWeight re-weights all weights to be non-negative)
private double reducedCost(int i, int j) {
double reducedCost = (weight[i][j] - minWeight) + px[i] - py[j];
// to avoid issues with floating-point precision
double magnitude = Math.abs(weight[i][j]) + Math.abs(px[i]) + Math.abs(py[j]);
if (Math.abs(reducedCost) <= FLOATING_POINT_EPSILON * magnitude) return 0.0;
assert reducedCost >= 0.0;
return reducedCost;
}
/**
* Returns the dual optimal value for the specified row.
*
* @param i the row index
* @return the dual optimal value for row {@code i}
* @throws IllegalArgumentException unless {@code 0 <= i < n}
*
*/
// dual variable for row i
public double dualRow(int i) {
validate(i);
return px[i];
}
/**
* Returns the dual optimal value for the specified column.
*
* @param j the column index
* @return the dual optimal value for column {@code j}
* @throws IllegalArgumentException unless {@code 0 <= j < n}
*
*/
public double dualCol(int j) {
validate(j);
return py[j];
}
/**
* Returns the column associated with the specified row in the optimal solution.
*
* @param i the row index
* @return the column matched to row {@code i} in the optimal solution
* @throws IllegalArgumentException unless {@code 0 <= i < n}
*
*/
public int sol(int i) {
validate(i);
return xy[i];
}
/**
* Returns the total weight of the optimal solution
*
* @return the total weight of the optimal solution
*
*/
public double weight() {
double total = 0.0;
for (int i = 0; i < n; i++) {
if (xy[i] != UNMATCHED)
total += weight[i][xy[i]];
}
return total;
}
private void validate(int i) {
if (i < 0 || i >= n) throw new IllegalArgumentException("index is not between 0 and " + (n-1) + ": " + i);
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// check that dual variables are feasible
private boolean isDualFeasible() {
// check that all edges have >= 0 reduced cost
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (reducedCost(i, j) < 0) {
StdOut.println("Dual variables are not feasible");
return false;
}
}
}
return true;
}
// check that primal and dual variables are complementary slack
private boolean isComplementarySlack() {
// check that all matched edges have 0-reduced cost
for (int i = 0; i < n; i++) {
if ((xy[i] != UNMATCHED) && (reducedCost(i, xy[i]) != 0)) {
StdOut.println("Primal and dual variables are not complementary slack");
return false;
}
}
return true;
}
// check that primal variables are a perfect matching
private boolean isPerfectMatching() {
// check that xy[] is a perfect matching
boolean[] perm = new boolean[n];
for (int i = 0; i < n; i++) {
if (perm[xy[i]]) {
StdOut.println("Not a perfect matching");
return false;
}
perm[xy[i]] = true;
}
// check that xy[] and yx[] are inverses
for (int j = 0; j < n; j++) {
if (xy[yx[j]] != j) {
StdOut.println("xy[] and yx[] are not inverses");
return false;
}
}
for (int i = 0; i < n; i++) {
if (yx[xy[i]] != i) {
StdOut.println("xy[] and yx[] are not inverses");
return false;
}
}
return true;
}
// check optimality conditions
private boolean certifySolution() {
return isPerfectMatching() && isDualFeasible() && isComplementarySlack();
}
/**
* Unit tests the {@code AssignmentProblem} data type.
* Takes a command-line argument n; creates a random n-by-n matrix;
* solves the n-by-n assignment problem; and prints the optimal
* solution.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// create random n-by-n matrix
int n = Integer.parseInt(args[0]);
double[][] weight = new double[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
weight[i][j] = StdRandom.uniformInt(900) + 100; // 3 digits
}
}
// solve assignment problem
AssignmentProblem assignment = new AssignmentProblem(weight);
StdOut.printf("weight = %.0f\n", assignment.weight());
StdOut.println();
// print n-by-n matrix and optimal solution
if (n >= 20) return;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (j == assignment.sol(i))
StdOut.printf("*%.0f ", weight[i][j]);
else
StdOut.printf(" %.0f ", weight[i][j]);
}
StdOut.println();
}
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/Average.java
================================================
/******************************************************************************
* Compilation: javac Average.java
* Execution: java Average < data.txt
* Dependencies: StdIn.java StdOut.java
*
* Reads in a sequence of real numbers, and computes their average.
*
* % java Average
* 10.0 5.0 6.0
* 3.0 7.0 32.0
* [Ctrl-d]
* Average is 10.5
*
* Note [Ctrl-d] signifies the end of file on Unix.
* On windows use [Ctrl-z].
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code Average} class provides a client for reading in a sequence
* of real numbers and printing out their average.
*
* For additional documentation, see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Average {
// this class should not be instantiated
private Average() { }
/**
* Reads in a sequence of real numbers from standard input and prints
* out their average to standard output.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int count = 0; // number input values
double sum = 0.0; // sum of input values
// read data and compute statistics
while (!StdIn.isEmpty()) {
double value = StdIn.readDouble();
sum += value;
count++;
}
// compute the average
double average = sum / count;
// print results
StdOut.println("Average is " + average);
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BST.java
================================================
/******************************************************************************
* Compilation: javac BST.java
* Execution: java BST
* Dependencies: StdIn.java StdOut.java Queue.java
* Data files: https://algs4.cs.princeton.edu/32bst/tinyST.txt
*
* A symbol table implemented with a binary search tree.
*
* % more tinyST.txt
* S E A R C H E X A M P L E
*
* % java BST < tinyST.txt
* A 8
* C 4
* E 12
* H 5
* L 11
* M 9
* P 10
* R 3
* S 0
* X 7
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.util.NoSuchElementException;
/**
* The {@code BST} class represents an ordered symbol table of generic
* key-value pairs.
* It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides ordered methods for finding the minimum,
* maximum, floor, select, ceiling.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {@link java.util.Map}, this class uses the convention that
* values cannot be {@code null}—setting the
* value associated with a key to {@code null} is equivalent to deleting the key
* from the symbol table.
*
* It requires that
* the key type implements the {@code Comparable} interface and calls the
* {@code compareTo()} and method to compare two keys. It does not call either
* {@code equals()} or {@code hashCode()}.
*
* This implementation uses an (unbalanced) binary search tree.
* The put, contains, remove, minimum,
* maximum, ceiling, floor, select, and
* rank operations each take Θ(n) time in the worst
* case, where n is the number of key-value pairs.
* The size and is-empty operations take Θ(1) time.
* The keys method takes Θ(n) time in the worst case.
* Construction takes Θ(1) time.
*
* For alternative implementations of the symbol table API, see {@link ST},
* {@link BinarySearchST}, {@link SequentialSearchST}, {@link RedBlackBST},
* {@link SeparateChainingHashST}, and {@link LinearProbingHashST},
* For additional documentation, see
* Section 3.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BST
* This implementation uses a B-tree. It requires that
* the key type implements the {@code Comparable} interface and calls the
* {@code compareTo()} and method to compare two keys. It does not call either
* {@code equals()} or {@code hashCode()}.
* The get, put, and contains operations
* each make logm(n) probes in the worst case,
* where n is the number of key-value pairs
* and m is the branching factor.
* The size, and is-empty operations take constant time.
* Construction takes constant time.
*
* For additional documentation, see
* Section 6.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public class BTree
* This implementation uses a singly linked list with a static nested class Node.
* See {@link LinkedBag} for the version from the
* textbook that uses a non-static nested class.
* See {@link ResizingArrayBag} for a version that uses a resizing array.
* The add, isEmpty, and size operations
* take constant time. Iteration takes time proportional to the number of items.
*
* For additional documentation, see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*
* @param
* This implementation uses a queue-based implementation of
* the Bellman-Ford-Moore algorithm.
* The constructor takes Θ(E V) time
* in the worst case, where V is the number of vertices and
* E is the number of edges. In practice, it performs much better.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted digraph).
*
* This correctly computes shortest 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 BellmanFordSP {
// for floating-point precision issues
private static final double EPSILON = 1E-14;
private double[] distTo; // distTo[v] = distance of shortest s->v path
private DirectedEdge[] edgeTo; // edgeTo[v] = last edge on shortest s->v path
private boolean[] onQueue; // onQueue[v] = is v currently on the queue?
private Queue
* For more full-featured versions, see the Unix utilities
* {@code od} (octal dump) and {@code hexdump} (hexadecimal dump).
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* See also {@link HexDump} and {@link PictureDump}.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BinaryDump {
// Do not instantiate.
private BinaryDump() { }
/**
* Reads in a sequence of bytes from standard input and writes
* them to standard output in binary, k bits per line,
* where k is given as a command-line integer (defaults
* to 16 if no integer is specified); also writes the number
* of bits.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int bitsPerLine = 16;
if (args.length == 1) {
bitsPerLine = Integer.parseInt(args[0]);
}
int count;
for (count = 0; !BinaryStdIn.isEmpty(); count++) {
if (bitsPerLine == 0) {
BinaryStdIn.readBoolean();
continue;
}
else if (count != 0 && count % bitsPerLine == 0) StdOut.println();
if (BinaryStdIn.readBoolean()) StdOut.print(1);
else StdOut.print(0);
}
if (bitsPerLine != 0) StdOut.println();
StdOut.println(count + " bits");
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BinaryIn.java
================================================
/******************************************************************************
* Compilation: javac BinaryIn.java
* Execution: java BinaryIn input output
* Dependencies: none
*
* This library is for reading binary data from an input stream.
*
* % java BinaryIn https://introcs.cs.princeton.edu/java/cover.png output.png
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.NoSuchElementException;
/**
* The
* The binary input stream can be from standard input, a filename,
* a URL name, a Socket, or an InputStream.
*
* All primitive types are assumed to be represented using their
* standard Java representations, in big-endian (most significant
* byte first) order.
*
* The client should not intermix calls to {@code BinaryIn} with calls
* to {@code In}; otherwise unexpected behavior will result.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class BinaryIn {
private static final int EOF = -1; // end of file
private BufferedInputStream in; // the input stream
private int buffer; // one character buffer
private int n; // number of bits left in buffer
/**
* Initializes a binary input stream from standard input.
*/
public BinaryIn() {
in = new BufferedInputStream(System.in);
fillBuffer();
}
/**
* Initializes a binary input stream from an {@code InputStream}.
*
* @param is the {@code InputStream} object
*/
public BinaryIn(InputStream is) {
in = new BufferedInputStream(is);
fillBuffer();
}
/**
* Initializes a binary input stream from a socket.
*
* @param socket the socket
*/
public BinaryIn(Socket socket) {
try {
InputStream is = socket.getInputStream();
in = new BufferedInputStream(is);
fillBuffer();
}
catch (IOException ioe) {
System.err.println("could not read socket: " + socket);
}
}
/**
* Initializes a binary input stream from a URL.
*
* @param url the URL
*/
public BinaryIn(URL url) {
try {
URLConnection site = url.openConnection();
InputStream is = site.getInputStream();
in = new BufferedInputStream(is);
fillBuffer();
}
catch (IOException ioe) {
System.err.println("could not open URL: '" + url + "'");
}
}
/**
* Initializes a binary input stream from a filename or URL name.
*
* @param name the name of the file or URL
*/
public BinaryIn(String name) {
try {
// first try to read file from local file system
File file = new File(name);
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
in = new BufferedInputStream(fis);
fillBuffer();
return;
}
// next try for files included in jar
URL url = getClass().getResource(name);
// or URL from web
if (url == null) {
URI uri = new URI(name);
if (uri.isAbsolute()) url = uri.toURL();
else throw new IllegalArgumentException("could not read: '" + name+ "'");
}
URLConnection site = url.openConnection();
InputStream is = site.getInputStream();
in = new BufferedInputStream(is);
fillBuffer();
}
catch (IOException | URISyntaxException e) {
System.err.println("could not open: '" + name + "'");
}
}
private void fillBuffer() {
try {
buffer = in.read();
n = 8;
}
catch (IOException e) {
System.err.println("EOF");
buffer = EOF;
n = -1;
}
}
/**
* Returns true if this binary input stream exists.
*
* @return {@code true} if this binary input stream exists;
* {@code false} otherwise
*/
public boolean exists() {
return in != null;
}
/**
* Returns true if this binary input stream is empty.
*
* @return {@code true} if this binary input stream is empty;
* {@code false} otherwise
*/
public boolean isEmpty() {
return buffer == EOF;
}
/**
* Reads the next bit of data from this binary input stream and return as a boolean.
*
* @return the next bit of data from this binary input stream as a {@code boolean}
* @throws NoSuchElementException if this binary input stream is empty
*/
public boolean readBoolean() {
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
n--;
boolean bit = ((buffer >> n) & 1) == 1;
if (n == 0) fillBuffer();
return bit;
}
/**
* Reads the next 8 bits from this binary input stream and return as an 8-bit char.
*
* @return the next 8 bits of data from this binary input stream as a {@code char}
* @throws NoSuchElementException if there are fewer than 8 bits available
*/
public char readChar() {
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
// special case when aligned byte
if (n == 8) {
int x = buffer;
fillBuffer();
return (char) (x & 0xff);
}
// combine last N bits of current buffer with first 8-N bits of new buffer
int x = buffer;
x <<= (8 - n);
int oldN = n;
fillBuffer();
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
n = oldN;
x |= (buffer >>> n);
return (char) (x & 0xff);
// the above code doesn't quite work for the last character if N = 8
// because buffer will be -1
}
/**
* Reads the next r bits from this binary input stream and return
* as an r-bit character.
*
* @param r number of bits to read
* @return the next {@code r} bits of data from this binary input stream as a {@code char}
* @throws NoSuchElementException if there are fewer than {@code r} bits available
* @throws IllegalArgumentException unless {@code 1 <= r <= 16}
*/
public char readChar(int r) {
if (r < 1 || r > 16) throw new IllegalArgumentException("Illegal value of r = " + r);
// optimize r = 8 case
if (r == 8) return readChar();
char x = 0;
for (int i = 0; i < r; i++) {
x <<= 1;
boolean bit = readBoolean();
if (bit) x |= 1;
}
return x;
}
/**
* Reads the remaining bytes of data from this binary input stream and return as a string.
*
* @return the remaining bytes of data from this binary input stream as a {@code String}
* @throws NoSuchElementException if this binary input stream is empty or if the number of bits
* available is not a multiple of 8 (byte-aligned)
*/
public String readString() {
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
StringBuilder sb = new StringBuilder();
while (!isEmpty()) {
char c = readChar();
sb.append(c);
}
return sb.toString();
}
/**
* Reads the next 16 bits from this binary input stream and return as a 16-bit short.
*
* @return the next 16 bits of data from this binary input stream as a {@code short}
* @throws NoSuchElementException if there are fewer than 16 bits available
*/
public short readShort() {
short x = 0;
for (int i = 0; i < 2; i++) {
char c = readChar();
x <<= 8;
x |= c;
}
return x;
}
/**
* Reads the next 32 bits from this binary input stream and return as a 32-bit int.
*
* @return the next 32 bits of data from this binary input stream as a {@code int}
* @throws NoSuchElementException if there are fewer than 32 bits available
*/
public int readInt() {
int x = 0;
for (int i = 0; i < 4; i++) {
char c = readChar();
x <<= 8;
x |= c;
}
return x;
}
/**
* Reads the next r bits from this binary input stream return
* as an r-bit int.
*
* @param r number of bits to read
* @return the next {@code r} bits of data from this binary input stream as a {@code int}
* @throws NoSuchElementException if there are fewer than r bits available
* @throws IllegalArgumentException unless {@code 1 <= r <= 32}
*/
public int readInt(int r) {
if (r < 1 || r > 32) throw new IllegalArgumentException("Illegal value of r = " + r);
// optimize r = 32 case
if (r == 32) return readInt();
int x = 0;
for (int i = 0; i < r; i++) {
x <<= 1;
boolean bit = readBoolean();
if (bit) x |= 1;
}
return x;
}
/**
* Reads the next 64 bits from this binary input stream and return as a 64-bit long.
*
* @return the next 64 bits of data from this binary input stream as a {@code long}
* @throws NoSuchElementException if there are fewer than 64 bits available
*/
public long readLong() {
long x = 0;
for (int i = 0; i < 8; i++) {
char c = readChar();
x <<= 8;
x |= c;
}
return x;
}
/**
* Reads the next 64 bits from this binary input stream and return as a 64-bit double.
*
* @return the next 64 bits of data from this binary input stream as a {@code double}
* @throws NoSuchElementException if there are fewer than 64 bits available
*/
public double readDouble() {
return Double.longBitsToDouble(readLong());
}
/**
* Reads the next 32 bits from this binary input stream and return as a 32-bit float.
*
* @return the next 32 bits of data from this binary input stream as a {@code float}
* @throws NoSuchElementException if there are fewer than 32 bits available
*/
public float readFloat() {
return Float.intBitsToFloat(readInt());
}
/**
* Reads the next 8 bits from this binary input stream and return as an 8-bit byte.
*
* @return the next 8 bits of data from this binary input stream as a {@code byte}
* @throws NoSuchElementException if there are fewer than 8 bits available
*/
public byte readByte() {
char c = readChar();
return (byte) (c & 0xff);
}
/**
* Unit tests the {@code BinaryIn} data type.
* Reads the name of a file or URL (first command-line argument)
* and writes it to a file (second command-line argument).
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
BinaryIn in = new BinaryIn(args[0]);
BinaryOut out = new BinaryOut(args[1]);
// read one 8-bit char at a time
while (!in.isEmpty()) {
char c = in.readChar();
out.write(c);
}
out.flush();
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BinaryInsertion.java
================================================
/******************************************************************************
* Compilation: javac BinaryInsertion.java
* Execution: java BinaryInsertion < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/21elementary/tiny.txt
* https://algs4.cs.princeton.edu/21elementary/words3.txt
*
* Sorts a sequence of strings from standard input using
* binary insertion sort with half exchanges.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java BinaryInsertion < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java BinaryInsertion < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code BinaryInsertion} class provides a static method for sorting an
* array using an optimized binary insertion sort with half exchanges.
*
* In the worst case, this implementation makes
* ~ n log2n compares to sort an array of length
* n. However, in the worst case, the running time is
* Θ(n2) because the number of array accesses
* can be quadratic.
* As such, it is not suitable for sorting large arrays
* (unless the number of inversions is small).
*
* This sorting algorithm is stable.
* It uses Θ(1) extra memory (not including the input array).
*
* For additional documentation,
* see Section 2.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Ivan Pesin
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BinaryInsertion {
// This class should not be instantiated.
private BinaryInsertion() { }
/**
* Rearranges the array in ascending order, using the natural order.
* @param a the array to be sorted
*/
public static void sort(Comparable[] a) {
int n = a.length;
for (int i = 1; i < n; i++) {
// binary search to determine index j at which to insert a[i]
Comparable v = a[i];
int lo = 0, hi = i;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (less(v, a[mid])) hi = mid;
else lo = mid + 1;
}
// insertion sort with "half exchanges"
// (insert a[i] at index j and shift a[j], ..., a[i-1] to right)
for (int j = i; j > lo; --j)
a[j] = a[j-1];
a[lo] = v;
}
assert isSorted(a);
}
/***************************************************************************
* Helper sorting function.
***************************************************************************/
// is v < w ?
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private static boolean isSorted(Comparable[] a) {
return isSorted(a, 0, a.length - 1);
}
// is the array sorted from a[lo] to a[hi]
private static boolean isSorted(Comparable[] a, int lo, int hi) {
for (int i = lo+1; i <= hi; i++)
if (less(a[i], a[i-1])) return false;
return true;
}
// print array to standard output
private static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
StdOut.println(a[i]);
}
}
/**
* Reads in a sequence of strings from standard input; insertion sorts them;
* and prints them to standard output in ascending order.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
String[] a = StdIn.readAllStrings();
BinaryInsertion.sort(a);
show(a);
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BinaryOut.java
================================================
/******************************************************************************
* Compilation: javac BinaryOut.java
* Execution: java BinaryOut
* Dependencies: none
*
* Write binary data to an output stream, either one 1-bit boolean,
* one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
* or one 64-bit long at a time. The output stream can be standard
* output, a file, an OutputStream or a Socket.
*
* The bytes written are not aligned.
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* The
* The client must {@code flush()} the output stream when finished writing bits.
*
* The client should not intermix calls to {@code BinaryOut} with calls
* to {@code Out}; otherwise unexpected behavior will result.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class BinaryOut {
private BufferedOutputStream out; // the output stream
private int buffer; // 8-bit buffer of bits to write out
private int n; // number of bits remaining in buffer
/**
* Initializes a binary output stream from standard output.
*/
public BinaryOut() {
out = new BufferedOutputStream(System.out);
}
/**
* Initializes a binary output stream from an {@code OutputStream}.
* @param os the {@code OutputStream}
*/
public BinaryOut(OutputStream os) {
out = new BufferedOutputStream(os);
}
/**
* Initializes a binary output stream from a file.
* @param filename the name of the file
* @throws IllegalArgumentException if {@code filename} is {@code null}
* @throws IllegalArgumentException if {@code filename} is the empty string
* @throws IllegalArgumentException if cannot write the file {@code filename}
*/
public BinaryOut(String filename) {
if (filename == null) {
throw new IllegalArgumentException("filename argument is null");
}
if (filename.length() == 0) {
throw new IllegalArgumentException("filename argument is the empty string");
}
try {
OutputStream os = new FileOutputStream(filename);
out = new BufferedOutputStream(os);
}
catch (IOException e) {
throw new IllegalArgumentException("could not create file '" + filename + "' for writing", e);
}
}
/**
* Initializes a binary output stream from a socket.
* @param socket the socket
* @throws IllegalArgumentException if {@code filename} is {@code null}
* @throws IllegalArgumentException if cannot create output stream from socket
*/
public BinaryOut(Socket socket) {
if (socket == null) {
throw new IllegalArgumentException("socket argument is null");
}
try {
OutputStream os = socket.getOutputStream();
out = new BufferedOutputStream(os);
}
catch (IOException e) {
throw new IllegalArgumentException("could not create output stream from socket", e);
}
}
/**
* Writes the specified bit to the binary output stream.
* @param x the bit
*/
private void writeBit(boolean x) {
// add bit to buffer
buffer <<= 1;
if (x) buffer |= 1;
// if buffer is full (8 bits), write out as a single byte
n++;
if (n == 8) clearBuffer();
}
/**
* Writes the 8-bit byte to the binary output stream.
* @param x the byte
*/
private void writeByte(int x) {
assert x >= 0 && x < 256;
// optimized if byte-aligned
if (n == 0) {
try {
out.write(x);
}
catch (IOException e) {
e.printStackTrace();
}
return;
}
// otherwise write one bit at a time
for (int i = 0; i < 8; i++) {
boolean bit = ((x >>> (8 - i - 1)) & 1) == 1;
writeBit(bit);
}
}
// write out any remaining bits in buffer to the binary output stream, padding with 0s
private void clearBuffer() {
if (n == 0) return;
if (n > 0) buffer <<= (8 - n);
try {
out.write(buffer);
}
catch (IOException e) {
e.printStackTrace();
}
n = 0;
buffer = 0;
}
/**
* Flushes the binary output stream, padding 0s if number of bits written so far
* is not a multiple of 8.
*/
public void flush() {
clearBuffer();
try {
out.flush();
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Flushes and closes the binary output stream.
* Once it is closed, bits can no longer be written.
*/
public void close() {
flush();
try {
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Writes the specified bit to the binary output stream.
* @param x the {@code boolean} to write
*/
public void write(boolean x) {
writeBit(x);
}
/**
* Writes the 8-bit byte to the binary output stream.
* @param x the {@code byte} to write.
*/
public void write(byte x) {
writeByte(x & 0xff);
}
/**
* Writes the 32-bit int to the binary output stream.
* @param x the {@code int} to write
*/
public void write(int x) {
writeByte((x >>> 24) & 0xff);
writeByte((x >>> 16) & 0xff);
writeByte((x >>> 8) & 0xff);
writeByte((x >>> 0) & 0xff);
}
/**
* Writes the r-bit int to the binary output stream.
*
* @param x the {@code int} to write
* @param r the number of relevant bits in the char
* @throws IllegalArgumentException unless {@code r} is between 1 and 32
* @throws IllegalArgumentException unless {@code x} is between 0 and 2r - 1
*/
public void write(int x, int r) {
if (r == 32) {
write(x);
return;
}
if (r < 1 || r > 32) throw new IllegalArgumentException("Illegal value for r = " + r);
if (x >= (1 << r)) throw new IllegalArgumentException("Illegal " + r + "-bit char = " + x);
for (int i = 0; i < r; i++) {
boolean bit = ((x >>> (r - i - 1)) & 1) == 1;
writeBit(bit);
}
}
/**
* Writes the 64-bit double to the binary output stream.
* @param x the {@code double} to write
*/
public void write(double x) {
write(Double.doubleToRawLongBits(x));
}
/**
* Writes the 64-bit long to the binary output stream.
* @param x the {@code long} to write
*/
public void write(long x) {
writeByte((int) ((x >>> 56) & 0xff));
writeByte((int) ((x >>> 48) & 0xff));
writeByte((int) ((x >>> 40) & 0xff));
writeByte((int) ((x >>> 32) & 0xff));
writeByte((int) ((x >>> 24) & 0xff));
writeByte((int) ((x >>> 16) & 0xff));
writeByte((int) ((x >>> 8) & 0xff));
writeByte((int) ((x >>> 0) & 0xff));
}
/**
* Writes the 32-bit float to the binary output stream.
* @param x the {@code float} to write
*/
public void write(float x) {
write(Float.floatToRawIntBits(x));
}
/**
* Write the 16-bit int to the binary output stream.
* @param x the {@code short} to write.
*/
public void write(short x) {
writeByte((x >>> 8) & 0xff);
writeByte((x >>> 0) & 0xff);
}
/**
* Writes the 8-bit char to the binary output stream.
*
* @param x the {@code char} to write
* @throws IllegalArgumentException unless {@code x} is between 0 and 255
*/
public void write(char x) {
if (x >= 256) throw new IllegalArgumentException("Illegal 8-bit char = " + x);
writeByte(x);
}
/**
* Writes the r-bit char to the binary output stream.
*
* @param x the {@code char} to write
* @param r the number of relevant bits in the char
* @throws IllegalArgumentException unless {@code r} is between 1 and 16
* @throws IllegalArgumentException unless {@code x} is between 0 and 2r - 1
*/
public void write(char x, int r) {
if (r == 8) {
write(x);
return;
}
if (r < 1 || r > 16) throw new IllegalArgumentException("Illegal value for r = " + r);
if (x >= (1 << r)) throw new IllegalArgumentException("Illegal " + r + "-bit char = " + x);
for (int i = 0; i < r; i++) {
boolean bit = ((x >>> (r - i - 1)) & 1) == 1;
writeBit(bit);
}
}
/**
* Writes the string of 8-bit characters to the binary output stream.
*
* @param s the {@code String} to write
* @throws IllegalArgumentException if any character in the string is not
* between 0 and 255
*/
public void write(String s) {
for (int i = 0; i < s.length(); i++)
write(s.charAt(i));
}
/**
* Writes the string of r-bit characters to the binary output stream.
* @param s the {@code String} to write
* @param r the number of relevant bits in each character
* @throws IllegalArgumentException unless r is between 1 and 16
* @throws IllegalArgumentException if any character in the string is not
* between 0 and 2r - 1
*/
public void write(String s, int r) {
for (int i = 0; i < s.length(); i++)
write(s.charAt(i), r);
}
/**
* Test client. Read bits from standard input and write to the file
* specified on command line.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// create binary output stream to write to file
String filename = args[0];
BinaryOut out = new BinaryOut(filename);
BinaryIn in = new BinaryIn();
// read from standard input and write to file
while (!in.isEmpty()) {
char c = in.readChar();
out.write(c);
}
out.flush();
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BinarySearch.java
================================================
/******************************************************************************
* Compilation: javac BinarySearch.java
* Execution: java BinarySearch allowlist.txt < input.txt
* Dependencies: In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/11model/tinyAllowlist.txt
* https://algs4.cs.princeton.edu/11model/tinyText.txt
* https://algs4.cs.princeton.edu/11model/largeAllowlist.txt
* https://algs4.cs.princeton.edu/11model/largeText.txt
*
* % java BinarySearch tinyAllowlist.txt < tinyText.txt
* 50
* 99
* 13
*
* % java BinarySearch largeAllowlist.txt < largeText.txt | more
* 499569
* 984875
* 295754
* 207807
* 140925
* 161828
* [367,966 total values]
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.util.Arrays;
/**
* The {@code BinarySearch} class provides a static method for binary
* searching for an integer in a sorted array of integers.
*
* The indexOf operations takes logarithmic time in the worst case.
*
* For additional documentation, see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BinarySearch {
/**
* This class should not be instantiated.
*/
private BinarySearch() { }
/**
* Returns the index of the specified key in the specified array.
*
* @param a the array of integers, must be sorted in ascending order
* @param key the search key
* @return index of key in array {@code a} if present; {@code -1} otherwise
*/
public static int indexOf(int[] a, int key) {
int lo = 0;
int hi = a.length - 1;
while (lo <= hi) {
// Key is in a[lo..hi] or not present.
int mid = lo + (hi - lo) / 2;
if (key < a[mid]) hi = mid - 1;
else if (key > a[mid]) lo = mid + 1;
else return mid;
}
return -1;
}
/**
* Returns the index of the specified key in the specified array.
* This function is poorly named because it does not give the rank
* if the array has duplicate keys or if the key is not in the array.
*
* @param key the search key
* @param a the array of integers, must be sorted in ascending order
* @return index of key in array {@code a} if present; {@code -1} otherwise
* @deprecated Replaced by {@link #indexOf(int[], int)}.
*/
@Deprecated
public static int rank(int key, int[] a) {
return indexOf(a, key);
}
/**
* Reads in a sequence of integers from the allowlist file, specified as
* a command-line argument; reads in integers from standard input;
* prints to standard output those integers that do not appear in the file.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// read the integers from a file
In in = new In(args[0]);
int[] allowlist = in.readAllInts();
// sort the array
Arrays.sort(allowlist);
// read integer key from standard input; print if not in allowlist
while (!StdIn.isEmpty()) {
int key = StdIn.readInt();
if (BinarySearch.indexOf(allowlist, key) == -1)
StdOut.println(key);
}
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BinarySearchST.java
================================================
/******************************************************************************
* Compilation: javac BinarySearchST.java
* Execution: java BinarySearchST
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/31elementary/tinyST.txt
*
* Symbol table implementation with binary search in an ordered array.
*
* % more tinyST.txt
* S E A R C H E X A M P L E
*
* % java BinarySearchST < tinyST.txt
* A 8
* C 4
* E 12
* H 5
* L 11
* M 9
* P 10
* R 3
* S 0
* X 7
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.util.NoSuchElementException;
/**
* The {@code BST} class represents an ordered symbol table of generic
* key-value pairs.
* It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides ordered methods for finding the minimum,
* maximum, floor, select, and ceiling.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {@link java.util.Map}, this class uses the convention that
* values cannot be {@code null}—setting the
* value associated with a key to {@code null} is equivalent to deleting the key
* from the symbol table.
*
* It requires that
* the key type implements the {@code Comparable} interface and calls the
* {@code compareTo()} and method to compare two keys. It does not call either
* {@code equals()} or {@code hashCode()}.
*
* This implementation uses a sorted array.
* The put and remove operations take Θ(n)
* time in the worst case.
* The contains, ceiling, floor,
* and rank operations take Θ(log n) time in the worst
* case.
* The size, is-empty, minimum, maximum,
* and select operations take Θ(1) time.
* Construction takes Θ(1) time.
*
* For alternative implementations of the symbol table API,
* see {@link ST}, {@link BST}, {@link SequentialSearchST}, {@link RedBlackBST},
* {@link SeparateChainingHashST}, and {@link LinearProbingHashST},
* For additional documentation,
* see Section 3.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public class BinarySearchST
* All primitive types are assumed to be represented using their
* standard Java representations, in big-endian (most significant
* byte first) order.
*
* The client should not intermix calls to {@code BinaryStdIn} with calls
* to {@code StdIn} or {@code System.in};
* otherwise unexpected behavior will result.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class BinaryStdIn {
private static final int EOF = -1; // end of file
private static BufferedInputStream in; // input stream
private static int buffer; // one character buffer
private static int n; // number of bits left in buffer
private static boolean isInitialized; // has BinaryStdIn been called for first time?
// don't instantiate
private BinaryStdIn() { }
// fill buffer
private static void initialize() {
in = new BufferedInputStream(System.in);
buffer = 0;
n = 0;
fillBuffer();
isInitialized = true;
}
private static void fillBuffer() {
try {
buffer = in.read();
n = 8;
}
catch (IOException e) {
System.out.println("EOF");
buffer = EOF;
n = -1;
}
}
/**
* Close this input stream and release any associated system resources.
*/
public static void close() {
if (!isInitialized) initialize();
try {
in.close();
isInitialized = false;
}
catch (IOException ioe) {
throw new IllegalStateException("Could not close BinaryStdIn", ioe);
}
}
/**
* Returns true if standard input is empty.
* @return true if and only if standard input is empty
*/
public static boolean isEmpty() {
if (!isInitialized) initialize();
return buffer == EOF;
}
/**
* Reads the next bit of data from standard input and return as a boolean.
*
* @return the next bit of data from standard input as a {@code boolean}
* @throws NoSuchElementException if standard input is empty
*/
public static boolean readBoolean() {
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
n--;
boolean bit = ((buffer >> n) & 1) == 1;
if (n == 0) fillBuffer();
return bit;
}
/**
* Reads the next 8 bits from standard input and return as an 8-bit char.
* Note that {@code char} is a 16-bit type;
* to read the next 16 bits as a char, use {@code readChar(16)}.
*
* @return the next 8 bits of data from standard input as a {@code char}
* @throws NoSuchElementException if there are fewer than 8 bits available on standard input
*/
public static char readChar() {
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
// special case when aligned byte
if (n == 8) {
int x = buffer;
fillBuffer();
return (char) (x & 0xff);
}
// combine last n bits of current buffer with first 8-n bits of new buffer
int x = buffer;
x <<= (8 - n);
int oldN = n;
fillBuffer();
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
n = oldN;
x |= (buffer >>> n);
return (char) (x & 0xff);
// the above code doesn't quite work for the last character if n = 8
// because buffer will be -1, so there is a special case for aligned byte
}
/**
* Reads the next r bits from standard input and return as an r-bit character.
*
* @param r number of bits to read.
* @return the next r bits of data from standard input as a {@code char}
* @throws NoSuchElementException if there are fewer than {@code r} bits available on standard input
* @throws IllegalArgumentException unless {@code 1 <= r <= 16}
*/
public static char readChar(int r) {
if (r < 1 || r > 16) throw new IllegalArgumentException("Illegal value of r = " + r);
// optimize r = 8 case
if (r == 8) return readChar();
char x = 0;
for (int i = 0; i < r; i++) {
x <<= 1;
boolean bit = readBoolean();
if (bit) x |= 1;
}
return x;
}
/**
* Reads the remaining bytes of data from standard input and return as a string.
*
* @return the remaining bytes of data from standard input as a {@code String}
* @throws NoSuchElementException if standard input is empty or if the number of bits
* available on standard input is not a multiple of 8 (byte-aligned)
*/
public static String readString() {
if (isEmpty()) throw new NoSuchElementException("Reading from empty input stream");
StringBuilder sb = new StringBuilder();
while (!isEmpty()) {
char c = readChar();
sb.append(c);
}
return sb.toString();
}
/**
* Reads the next 16 bits from standard input and return as a 16-bit short.
*
* @return the next 16 bits of data from standard input as a {@code short}
* @throws NoSuchElementException if there are fewer than 16 bits available on standard input
*/
public static short readShort() {
short x = 0;
for (int i = 0; i < 2; i++) {
char c = readChar();
x <<= 8;
x |= c;
}
return x;
}
/**
* Reads the next 32 bits from standard input and return as a 32-bit int.
*
* @return the next 32 bits of data from standard input as a {@code int}
* @throws NoSuchElementException if there are fewer than 32 bits available on standard input
*/
public static int readInt() {
int x = 0;
for (int i = 0; i < 4; i++) {
char c = readChar();
x <<= 8;
x |= c;
}
return x;
}
/**
* Reads the next r bits from standard input and return as an r-bit int.
*
* @param r number of bits to read.
* @return the next r bits of data from standard input as a {@code int}
* @throws NoSuchElementException if there are fewer than {@code r} bits available on standard input
* @throws IllegalArgumentException unless {@code 1 <= r <= 32}
*/
public static int readInt(int r) {
if (r < 1 || r > 32) throw new IllegalArgumentException("Illegal value of r = " + r);
// optimize r = 32 case
if (r == 32) return readInt();
int x = 0;
for (int i = 0; i < r; i++) {
x <<= 1;
boolean bit = readBoolean();
if (bit) x |= 1;
}
return x;
}
/**
* Reads the next 64 bits from standard input and return as a 64-bit long.
*
* @return the next 64 bits of data from standard input as a {@code long}
* @throws NoSuchElementException if there are fewer than 64 bits available on standard input
*/
public static long readLong() {
long x = 0;
for (int i = 0; i < 8; i++) {
char c = readChar();
x <<= 8;
x |= c;
}
return x;
}
/**
* Reads the next 64 bits from standard input and return as a 64-bit double.
*
* @return the next 64 bits of data from standard input as a {@code double}
* @throws NoSuchElementException if there are fewer than 64 bits available on standard input
*/
public static double readDouble() {
return Double.longBitsToDouble(readLong());
}
/**
* Reads the next 32 bits from standard input and return as a 32-bit float.
*
* @return the next 32 bits of data from standard input as a {@code float}
* @throws NoSuchElementException if there are fewer than 32 bits available on standard input
*/
public static float readFloat() {
return Float.intBitsToFloat(readInt());
}
/**
* Reads the next 8 bits from standard input and return as an 8-bit byte.
*
* @return the next 8 bits of data from standard input as a {@code byte}
* @throws NoSuchElementException if there are fewer than 8 bits available on standard input
*/
public static byte readByte() {
char c = readChar();
return (byte) (c & 0xff);
}
/**
* Test client. Reads in a binary input file from standard input and writes
* it to standard output.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// read one 8-bit char at a time
while (!BinaryStdIn.isEmpty()) {
char c = BinaryStdIn.readChar();
BinaryStdOut.write(c);
}
BinaryStdOut.flush();
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BinaryStdOut.java
================================================
/******************************************************************************
* Compilation: javac BinaryStdOut.java
* Execution: java BinaryStdOut
* Dependencies: none
*
* Write binary data to standard output, either one 1-bit boolean,
* one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
* or one 64-bit long at a time.
*
* The bytes written are not aligned.
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.io.BufferedOutputStream;
import java.io.IOException;
/**
* The
* The client must {@code flush()} the output stream when finished writing bits.
*
* The client should not intermix calls to {@code BinaryStdOut} with calls
* to {@code StdOut} or {@code System.out}; otherwise unexpected behavior
* will result.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public final class BinaryStdOut {
private static BufferedOutputStream out; // output stream (standard output)
private static int buffer; // 8-bit buffer of bits to write
private static int n; // number of bits remaining in buffer
private static boolean isInitialized; // has BinaryStdOut been called for first time?
// don't instantiate
private BinaryStdOut() { }
// initialize BinaryStdOut
private static void initialize() {
out = new BufferedOutputStream(System.out);
buffer = 0;
n = 0;
isInitialized = true;
}
/**
* Writes the specified bit to standard output.
*/
private static void writeBit(boolean bit) {
if (!isInitialized) initialize();
// add bit to buffer
buffer <<= 1;
if (bit) buffer |= 1;
// if buffer is full (8 bits), write out as a single byte
n++;
if (n == 8) clearBuffer();
}
/**
* Writes the 8-bit byte to standard output.
*/
private static void writeByte(int x) {
if (!isInitialized) initialize();
assert x >= 0 && x < 256;
// optimized if byte-aligned
if (n == 0) {
try {
out.write(x);
}
catch (IOException e) {
e.printStackTrace();
}
return;
}
// otherwise write one bit at a time
for (int i = 0; i < 8; i++) {
boolean bit = ((x >>> (8 - i - 1)) & 1) == 1;
writeBit(bit);
}
}
// write out any remaining bits in buffer to standard output, padding with 0s
private static void clearBuffer() {
if (!isInitialized) initialize();
if (n == 0) return;
if (n > 0) buffer <<= (8 - n);
try {
out.write(buffer);
}
catch (IOException e) {
e.printStackTrace();
}
n = 0;
buffer = 0;
}
/**
* Flushes standard output, padding 0s if number of bits written so far
* is not a multiple of 8.
*/
public static void flush() {
clearBuffer();
try {
out.flush();
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Flushes and closes standard output. Once standard output is closed, you can no
* longer write bits to it.
*/
public static void close() {
flush();
try {
out.close();
isInitialized = false;
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Writes the specified bit to standard output.
* @param x the {@code boolean} to write.
*/
public static void write(boolean x) {
writeBit(x);
}
/**
* Writes the 8-bit byte to standard output.
* @param x the {@code byte} to write.
*/
public static void write(byte x) {
writeByte(x & 0xff);
}
/**
* Writes the 32-bit int to standard output.
* @param x the {@code int} to write.
*/
public static void write(int x) {
writeByte((x >>> 24) & 0xff);
writeByte((x >>> 16) & 0xff);
writeByte((x >>> 8) & 0xff);
writeByte((x >>> 0) & 0xff);
}
/**
* Writes the r-bit int to standard output.
* @param x the {@code int} to write.
* @param r the number of relevant bits in the char.
* @throws IllegalArgumentException if {@code r} is not between 1 and 32.
* @throws IllegalArgumentException if {@code x} is not between 0 and 2r - 1.
*/
public static void write(int x, int r) {
if (r == 32) {
write(x);
return;
}
if (r < 1 || r > 32) throw new IllegalArgumentException("Illegal value for r = " + r);
if (x < 0 || x >= (1 << r)) throw new IllegalArgumentException("Illegal " + r + "-bit char = " + x);
for (int i = 0; i < r; i++) {
boolean bit = ((x >>> (r - i - 1)) & 1) == 1;
writeBit(bit);
}
}
/**
* Writes the 64-bit double to standard output.
* @param x the {@code double} to write.
*/
public static void write(double x) {
write(Double.doubleToRawLongBits(x));
}
/**
* Writes the 64-bit long to standard output.
* @param x the {@code long} to write.
*/
public static void write(long x) {
writeByte((int) ((x >>> 56) & 0xff));
writeByte((int) ((x >>> 48) & 0xff));
writeByte((int) ((x >>> 40) & 0xff));
writeByte((int) ((x >>> 32) & 0xff));
writeByte((int) ((x >>> 24) & 0xff));
writeByte((int) ((x >>> 16) & 0xff));
writeByte((int) ((x >>> 8) & 0xff));
writeByte((int) ((x >>> 0) & 0xff));
}
/**
* Writes the 32-bit float to standard output.
* @param x the {@code float} to write.
*/
public static void write(float x) {
write(Float.floatToRawIntBits(x));
}
/**
* Writes the 16-bit int to standard output.
* @param x the {@code short} to write.
*/
public static void write(short x) {
writeByte((x >>> 8) & 0xff);
writeByte((x >>> 0) & 0xff);
}
/**
* Writes the 8-bit char to standard output.
* @param x the {@code char} to write.
* @throws IllegalArgumentException if {@code x} is not between 0 and 255.
*/
public static void write(char x) {
if (x < 0 || x >= 256) throw new IllegalArgumentException("Illegal 8-bit char = " + x);
writeByte(x);
}
/**
* Writes the r-bit char to standard output.
* @param x the {@code char} to write.
* @param r the number of relevant bits in the char.
* @throws IllegalArgumentException if {@code r} is not between 1 and 16.
* @throws IllegalArgumentException if {@code x} is not between 0 and 2r - 1.
*/
public static void write(char x, int r) {
if (r == 8) {
write(x);
return;
}
if (r < 1 || r > 16) throw new IllegalArgumentException("Illegal value for r = " + r);
if (x >= (1 << r)) throw new IllegalArgumentException("Illegal " + r + "-bit char = " + x);
for (int i = 0; i < r; i++) {
boolean bit = ((x >>> (r - i - 1)) & 1) == 1;
writeBit(bit);
}
}
/**
* Writes the string of 8-bit characters to standard output.
* @param s the {@code String} to write.
* @throws IllegalArgumentException if any character in the string is not
* between 0 and 255.
*/
public static void write(String s) {
for (int i = 0; i < s.length(); i++)
write(s.charAt(i));
}
/**
* Writes the string of r-bit characters to standard output.
* @param s the {@code String} to write.
* @param r the number of relevant bits in each character.
* @throws IllegalArgumentException if r is not between 1 and 16.
* @throws IllegalArgumentException if any character in the string is not
* between 0 and 2r - 1.
*/
public static void write(String s, int r) {
for (int i = 0; i < s.length(); i++)
write(s.charAt(i), r);
}
/**
* Tests the methods in this class.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int m = Integer.parseInt(args[0]);
// write n integers to binary standard output
for (int i = 0; i < m; i++) {
BinaryStdOut.write(i);
}
BinaryStdOut.flush();
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BinomialMinPQ.java
================================================
/******************************************************************************
* Compilation: javac BinomialMinPQ.java
* Execution:
*
* A binomial heap.
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.util.Iterator;
import java.util.Comparator;
import java.util.NoSuchElementException;
/**
* The BinomialMinPQ class represents a priority queue of generic keys.
* It supports the usual insert and delete-the-minimum operations,
* along with the merging of two heaps together.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
* It is possible to build the priority queue using a Comparator.
* If not, the natural order relation between the keys will be used.
*
* This implementation uses a binomial heap.
* The insert, delete-the-minimum, union, min-key
* and size operations take logarithmic time.
* The is-empty and constructor operations take constant time.
*
* @author Tristan Claverie
*/
public class BinomialMinPQ
* 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 graph).
* See {@link BipartiteX} for a nonrecursive version that uses breadth-first
* search.
*
* For additional documentation, see Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Bipartite {
private boolean isBipartite; // is the graph bipartite?
private boolean[] color; // color[v] gives vertices on one side of bipartition
private boolean[] marked; // marked[v] = true iff v has been visited in DFS
private int[] edgeTo; // edgeTo[v] = last edge on path to v
private Stack
* This implementation uses the alternating-path algorithm.
* It is equivalent to reducing to the maximum-flow problem and running
* the augmenting-path algorithm on the resulting flow network, but it
* does so with less overhead.
* The constructor takes O((E + V) V)
* time, where E is the number of edges and V is the
* number of vertices in the graph.
* It uses Θ(V) extra space (not including the graph).
*
* See also {@link HopcroftKarp}, which solves the problem in
* O(E sqrt(V)) using the Hopcroft-Karp
* algorithm and
* BipartiteMatchingToMaxflow,
* which solves the problem in O((E + V) V)
* time via a reduction to maxflow.
*
* For additional documentation, see
* Section 6.5
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BipartiteMatching {
private static final int UNMATCHED = -1;
private final int V; // number of vertices in the graph
private BipartiteX bipartition; // the bipartition
private int cardinality; // cardinality of current matching
private int[] mate; // mate[v] = w if v-w is an edge in current matching
// = -1 if v is not in current matching
private boolean[] inMinVertexCover; // inMinVertexCover[v] = true iff v is in min vertex cover
private boolean[] marked; // marked[v] = true iff v is reachable via alternating path
private int[] edgeTo; // edgeTo[v] = last edge on alternating path to v
/**
* Determines a maximum matching (and a minimum vertex cover)
* in a bipartite graph.
*
* @param G the bipartite graph
* @throws IllegalArgumentException if {@code G} is not bipartite
*/
public BipartiteMatching(Graph G) {
bipartition = new BipartiteX(G);
if (!bipartition.isBipartite()) {
throw new IllegalArgumentException("graph is not bipartite");
}
this.V = G.V();
// initialize empty matching
mate = new int[V];
for (int v = 0; v < V; v++)
mate[v] = UNMATCHED;
// alternating path algorithm
while (hasAugmentingPath(G)) {
// find one endpoint t in alternating path
int t = -1;
for (int v = 0; v < G.V(); v++) {
if (!isMatched(v) && edgeTo[v] != -1) {
t = v;
break;
}
}
// update the matching according to alternating path in edgeTo[] array
for (int v = t; v != -1; v = edgeTo[edgeTo[v]]) {
int w = edgeTo[v];
mate[v] = w;
mate[w] = v;
}
cardinality++;
}
// find min vertex cover from marked[] array
inMinVertexCover = new boolean[V];
for (int v = 0; v < V; v++) {
if (bipartition.color(v) && !marked[v]) inMinVertexCover[v] = true;
if (!bipartition.color(v) && marked[v]) inMinVertexCover[v] = true;
}
assert certifySolution(G);
}
/*
* is there an augmenting path?
* - if so, upon termination adj[] contains the level graph;
* - if not, upon termination marked[] specifies those vertices reachable via an alternating
* path from one side of the bipartition
*
* an alternating path is a path whose edges belong alternately to the matching and not
* to the matching
*
* an augmenting path is an alternating path that starts and ends at unmatched vertices
*
* this implementation finds a shortest augmenting path (fewest number of edges), though there
* is no particular advantage to do so here
*/
private boolean hasAugmentingPath(Graph G) {
marked = new boolean[V];
edgeTo = new int[V];
for (int v = 0; v < V; v++)
edgeTo[v] = -1;
// breadth-first search (starting from all unmatched vertices on one side of bipartition)
Queue
* This implementation uses breadth-first search and is nonrecursive.
* The constructor takes Θ(V + E) time in
* 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 graph).
* See {@link Bipartite} for a recursive version that uses depth-first search.
*
* For additional documentation,
* see Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BipartiteX {
private static final boolean WHITE = false;
private static final boolean BLACK = true;
private boolean isBipartite; // is the graph bipartite?
private boolean[] color; // color[v] gives vertices on one side of bipartition
private boolean[] marked; // marked[v] = true iff v has been visited in DFS
private int[] edgeTo; // edgeTo[v] = last edge on path to v
private Queue
* For additional documentation,
* see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BlockFilter {
// Do not instantiate.
private BlockFilter() { }
public static void main(String[] args) {
SET
* 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
* This implementation uses the Boyer-Moore algorithm (with the bad-character
* rule, but not the strong good suffix rule).
*
* For additional documentation,
* see Section 5.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public class BoyerMoore {
private final int R; // the radix
private int[] right; // the bad-character skip array
private char[] pattern; // store the pattern as a character array
private String pat; // or as a string
/**
* Preprocesses the pattern string.
*
* @param pat the pattern string
*/
public BoyerMoore(String pat) {
this.R = 256;
this.pat = pat;
// position of rightmost occurrence of c in the pattern
right = new int[R];
for (int c = 0; c < R; c++)
right[c] = -1;
for (int j = 0; j < pat.length(); j++)
right[pat.charAt(j)] = j;
}
/**
* Preprocesses the pattern string.
*
* @param pattern the pattern string
* @param R the alphabet size
*/
public BoyerMoore(char[] pattern, int R) {
this.R = R;
this.pattern = new char[pattern.length];
for (int j = 0; j < pattern.length; j++)
this.pattern[j] = pattern[j];
// position of rightmost occurrence of c in the pattern
right = new int[R];
for (int c = 0; c < R; c++)
right[c] = -1;
for (int j = 0; j < pattern.length; j++)
right[pattern[j]] = j;
}
/**
* Returns the index of the first occurrence of the pattern string
* in the text string.
*
* @param txt the text string
* @return the index of the first occurrence of the pattern string
* in the text string; n if no such match
*/
public int search(String txt) {
int m = pat.length();
int n = txt.length();
int skip;
for (int i = 0; i <= n - m; i += skip) {
skip = 0;
for (int j = m-1; j >= 0; j--) {
if (pat.charAt(j) != txt.charAt(i+j)) {
skip = Math.max(1, j - right[txt.charAt(i+j)]);
break;
}
}
if (skip == 0) return i; // found
}
return n; // not found
}
/**
* Returns the index of the first occurrence of the pattern string
* in the text string.
*
* @param text the text string
* @return the index of the first occurrence of the pattern string
* in the text string; n if no such match
*/
public int search(char[] text) {
int m = pattern.length;
int n = text.length;
int skip;
for (int i = 0; i <= n - m; i += skip) {
skip = 0;
for (int j = m-1; j >= 0; j--) {
if (pattern[j] != text[i+j]) {
skip = Math.max(1, j - right[text[i+j]]);
break;
}
}
if (skip == 0) return i; // found
}
return n; // not found
}
/**
* Takes a pattern string and an input string as command-line arguments;
* searches for the pattern string in the text string; and prints
* the first occurrence of the pattern string in the text string.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
String pat = args[0];
String txt = args[1];
char[] pattern = pat.toCharArray();
char[] text = txt.toCharArray();
BoyerMoore boyermoore1 = new BoyerMoore(pat);
BoyerMoore boyermoore2 = new BoyerMoore(pattern, 256);
int offset1 = boyermoore1.search(txt);
int offset2 = boyermoore2.search(text);
// print results
StdOut.println("text: " + txt);
StdOut.print("pattern: ");
for (int i = 0; i < offset1; i++)
StdOut.print(" ");
StdOut.println(pat);
StdOut.print("pattern: ");
for (int i = 0; i < offset2; i++)
StdOut.print(" ");
StdOut.println(pat);
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/BreadthFirstDirectedPaths.java
================================================
/******************************************************************************
* Compilation: javac BreadthFirstDirectedPaths.java
* Execution: java BreadthFirstDirectedPaths digraph.txt s
* Dependencies: Digraph.java Queue.java Stack.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Run breadth-first search on a digraph.
* Runs in O(E + V) time.
*
* % java BreadthFirstDirectedPaths tinyDG.txt 3
* 3 to 0 (2): 3->2->0
* 3 to 1 (3): 3->2->0->1
* 3 to 2 (1): 3->2
* 3 to 3 (0): 3
* 3 to 4 (2): 3->5->4
* 3 to 5 (1): 3->5
* 3 to 6 (-): not connected
* 3 to 7 (-): not connected
* 3 to 8 (-): not connected
* 3 to 9 (-): not connected
* 3 to 10 (-): not connected
* 3 to 11 (-): not connected
* 3 to 12 (-): not connected
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code BreadthDirectedFirstPaths} class represents a data type for
* finding shortest paths (number of edges) from a source vertex s
* (or set of source vertices) to every other vertex in the digraph.
*
* This implementation uses breadth-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).
*
* 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 BreadthFirstDirectedPaths {
private static final int INFINITY = Integer.MAX_VALUE;
private boolean[] marked; // marked[v] = is there an s->v path?
private int[] edgeTo; // edgeTo[v] = last edge on shortest s->v path
private int[] distTo; // distTo[v] = length of shortest s->v path
/**
* Computes the shortest path from {@code s} and every other vertex in {@code digraph}.
* @param digraph the digraph
* @param s the source vertex
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public BreadthFirstDirectedPaths(Digraph digraph, int s) {
marked = new boolean[digraph.V()];
distTo = new int[digraph.V()];
edgeTo = new int[digraph.V()];
for (int v = 0; v < digraph.V(); v++)
distTo[v] = INFINITY;
validateVertex(s);
bfs(digraph, s);
}
/**
* Computes the shortest path from any one of the source vertices in {@code sources}
* to every other vertex in {@code digraph}.
* @param digraph the digraph
* @param sources the source vertices
* @throws IllegalArgumentException if {@code sources} is {@code null}
* @throws IllegalArgumentException if {@code sources} contains no vertices
* @throws IllegalArgumentException unless each vertex {@code v} in
* {@code sources} satisfies {@code 0 <= v < V}
*/
public BreadthFirstDirectedPaths(Digraph digraph, Iterable
* This implementation uses breadth-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 graph).
*
* For additional documentation,
* see Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class BreadthFirstPaths {
private static final int INFINITY = Integer.MAX_VALUE;
private boolean[] marked; // marked[v] = is there an s-v path
private int[] edgeTo; // edgeTo[v] = previous edge on shortest s-v path
private int[] distTo; // distTo[v] = number of edges shortest s-v path
/**
* Computes the shortest path between the source vertex {@code s}
* and every other vertex in the undirected graph {@code graph}.
* @param graph the graph
* @param s the source vertex
* @throws IllegalArgumentException unless {@code 0 <= s < V}
*/
public BreadthFirstPaths(Graph graph, int s) {
marked = new boolean[graph.V()];
distTo = new int[graph.V()];
edgeTo = new int[graph.V()];
validateVertex(s);
bfs(graph, s);
assert check(graph, s);
}
/**
* Computes the shortest path between any one of the source vertices in {@code sources}
* and every other vertex in {@code graph}.
* @param graph the graph
* @param sources the source vertices
* @throws IllegalArgumentException if {@code sources} is {@code null}
* @throws IllegalArgumentException if {@code sources} contains no vertices
* @throws IllegalArgumentException unless {@code 0 <= s < V} for each vertex
* {@code s} in {@code sources}
*/
public BreadthFirstPaths(Graph graph, Iterable
* The component identifier of a vertex is an integer between
* 0 and k–1, where k is the number of connected components.
* Two vertices have the same component identifier if and only if
* they are in the same connected component.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time,
* 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 graph).
*
* For additional documentation, see
* Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class CC {
private boolean[] marked; // marked[v] = has vertex v been marked?
private int[] id; // id[v] = id of connected component containing v
private int[] size; // size[id] = number of vertices in given component
private int count; // number of connected components
/**
* Computes the connected components of the undirected graph {@code graph}.
*
* @param graph the undirected graph
*/
public CC(Graph graph) {
marked = new boolean[graph.V()];
id = new int[graph.V()];
size = new int[graph.V()];
for (int v = 0; v < graph.V(); v++) {
if (!marked[v]) {
dfs(graph, v);
count++;
}
}
}
/**
* Computes the connected components of the edge-weighted graph {@code graph}.
*
* @param graph the edge-weighted graph
*/
public CC(EdgeWeightedGraph graph) {
marked = new boolean[graph.V()];
id = new int[graph.V()];
size = new int[graph.V()];
for (int v = 0; v < graph.V(); v++) {
if (!marked[v]) {
dfs(graph, v);
count++;
}
}
}
// depth-first search for a Graph
private void dfs(Graph graph, int v) {
marked[v] = true;
id[v] = count;
size[count]++;
for (int w : graph.adj(v)) {
if (!marked[w]) {
dfs(graph, w);
}
}
}
// depth-first search for an EdgeWeightedGraph
private void dfs(EdgeWeightedGraph graph, int v) {
marked[v] = true;
id[v] = count;
size[count]++;
for (Edge e : graph.adj(v)) {
int w = e.other(v);
if (!marked[w]) {
dfs(graph, w);
}
}
}
/**
* Returns the component id of the connected component containing vertex {@code v}.
*
* @param v the vertex
* @return the component id of the connected component containing vertex {@code v}
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public int id(int v) {
validateVertex(v);
return id[v];
}
/**
* Returns the number of vertices in the connected component containing vertex {@code v}.
*
* @param v the vertex
* @return the number of vertices in the connected component containing vertex {@code v}
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public int size(int v) {
validateVertex(v);
return size[id[v]];
}
/**
* Returns the number of connected components in the graph {@code G}.
*
* @return the number of connected components in the graph {@code G}
*/
public int count() {
return count;
}
/**
* Returns true if vertices {@code v} and {@code w} are in the same
* connected component.
*
* @param v one vertex
* @param w the other vertex
* @return {@code true} if vertices {@code v} and {@code w} are in the same
* connected component; {@code false} otherwise
* @throws IllegalArgumentException unless {@code 0 <= v < V}
* @throws IllegalArgumentException unless {@code 0 <= w < V}
*/
public boolean connected(int v, int w) {
validateVertex(v);
validateVertex(w);
return id(v) == id(w);
}
/**
* Returns true if vertices {@code v} and {@code w} are in the same
* connected component.
*
* @param v one vertex
* @param w the other vertex
* @return {@code true} if vertices {@code v} and {@code w} are in the same
* connected component; {@code false} otherwise
* @throws IllegalArgumentException unless {@code 0 <= v < V}
* @throws IllegalArgumentException unless {@code 0 <= w < V}
* @deprecated Replaced by {@link #connected(int, int)}.
*/
@Deprecated
public boolean areConnected(int v, int w) {
validateVertex(v);
validateVertex(w);
return id(v) == id(w);
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private void validateVertex(int v) {
int V = marked.length;
if (v < 0 || v >= V)
throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
}
/**
* Unit tests the {@code CC} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
In in = new In(args[0]);
Graph graph = new Graph(in);
CC cc = new CC(graph);
// number of connected components
int m = cc.count();
StdOut.println(m + " components");
// compute list of vertices in each connected component
Queue
* This implementation uses {@link AcyclicLP} to find a longest
* path in a DAG.
* The program takes Θ(V + E) time in
* the worst case, where V is the number of jobs and
* E is the number of precedence constraints.
*
* 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 CPM {
// this class cannot be instantiated
private CPM() { }
/**
* Reads the precedence constraints from standard input
* and prints a feasible schedule to standard output.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
// number of jobs
int n = StdIn.readInt();
// source and sink
int source = 2*n;
int sink = 2*n + 1;
// build network
EdgeWeightedDigraph G = new EdgeWeightedDigraph(2*n + 2);
for (int i = 0; i < n; i++) {
double duration = StdIn.readDouble();
G.addEdge(new DirectedEdge(source, i, 0.0));
G.addEdge(new DirectedEdge(i+n, sink, 0.0));
G.addEdge(new DirectedEdge(i, i+n, duration));
// precedence constraints
int m = StdIn.readInt();
for (int j = 0; j < m; j++) {
int precedent = StdIn.readInt();
G.addEdge(new DirectedEdge(n+i, precedent, 0.0));
}
}
// compute longest path
AcyclicLP lp = new AcyclicLP(G, source);
// print results
StdOut.println(" job start finish");
StdOut.println("--------------------");
for (int i = 0; i < n; i++) {
StdOut.printf("%4d %7.1f %7.1f\n", i, lp.distTo(i), lp.distTo(i+n));
}
StdOut.printf("Finish time: %7.1f\n", lp.distTo(sink));
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/Cat.java
================================================
/******************************************************************************
* Compilation: javac Cat.java
* Execution: java Cat input0.txt input1.txt ... output.txt
* Dependencies: In.java Out.java
* Data files: https://algs4.cs.princeton.edu/11model/in1.txt
* https://algs4.cs.princeton.edu/11model/in2.txt
*
* Reads in text files specified as the first command-line
* arguments, concatenates them, and writes the result to
* filename specified as the last command-line arguments.
*
* % more in1.txt
* This is
*
* % more in2.txt
* a tiny
* test.
*
* % java Cat in1.txt in2.txt out.txt
*
* % more out.txt
* This is
* a tiny
* test.
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code Cat} class provides a client for concatenating the results
* of several text files.
*
* For additional documentation, see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Cat {
// this class should not be instantiated
private Cat() { }
/**
* Reads in a sequence of text files specified as the first command-line
* arguments, concatenates them, and writes the results to the file
* specified as the last command-line argument.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
Out out = new Out(args[args.length - 1]);
for (int i = 0; i < args.length - 1; i++) {
In in = new In(args[i]);
String s = in.readAll();
out.println(s);
in.close();
}
out.close();
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/ClosestPair.java
================================================
/******************************************************************************
* Compilation: javac ClosestPair.java
* Execution: java ClosestPair < input.txt
* Dependencies: Point2D.java
* Data files: https://algs4.cs.princeton.edu/99hull/rs1423.txt
* https://algs4.cs.princeton.edu/99hull/kw1260.txt
*
* Given n points in the plane, find the closest pair in n log n time.
*
* Note: could speed it up by comparing square of Euclidean distances
* instead of Euclidean distances.
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.util.Arrays;
/**
* The {@code ClosestPair} data type computes a closest pair of points
* in a set of n points in the plane and provides accessor methods
* for getting the closest pair of points and the distance between them.
* The distance between two points is their Euclidean distance.
*
* This implementation uses a divide-and-conquer algorithm.
* It runs in O(n log n) time in the worst case and uses
* O(n) extra space.
*
* See also {@link FarthestPair}.
*
* For additional documentation, see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class ClosestPair {
// closest pair of points and their Euclidean distance
private Point2D best1, best2;
private double bestDistance = Double.POSITIVE_INFINITY;
/**
* Computes the closest pair of points in the specified array of points.
*
* @param points the array of points
* @throws IllegalArgumentException if {@code points} is {@code null} or if any
* entry in {@code points[]} is {@code null}
*/
public ClosestPair(Point2D[] points) {
if (points == null) throw new IllegalArgumentException("constructor argument is null");
for (int i = 0; i < points.length; i++) {
if (points[i] == null) throw new IllegalArgumentException("array element " + i + " is null");
}
int n = points.length;
if (n <= 1) return;
// sort by x-coordinate (breaking ties by y-coordinate via stability)
Point2D[] pointsByX = new Point2D[n];
for (int i = 0; i < n; i++)
pointsByX[i] = points[i];
Arrays.sort(pointsByX, Point2D.Y_ORDER);
Arrays.sort(pointsByX, Point2D.X_ORDER);
// check for coincident points
for (int i = 0; i < n-1; i++) {
if (pointsByX[i].equals(pointsByX[i+1])) {
bestDistance = 0.0;
best1 = pointsByX[i];
best2 = pointsByX[i+1];
return;
}
}
// sort by y-coordinate (but not yet sorted)
Point2D[] pointsByY = new Point2D[n];
for (int i = 0; i < n; i++)
pointsByY[i] = pointsByX[i];
// auxiliary array
Point2D[] aux = new Point2D[n];
closest(pointsByX, pointsByY, aux, 0, n-1);
}
// find closest pair of points in pointsByX[lo..hi]
// precondition: pointsByX[lo..hi] and pointsByY[lo..hi] are the same sequence of points
// precondition: pointsByX[lo..hi] sorted by x-coordinate
// postcondition: pointsByY[lo..hi] sorted by y-coordinate
private double closest(Point2D[] pointsByX, Point2D[] pointsByY, Point2D[] aux, int lo, int hi) {
if (hi <= lo) return Double.POSITIVE_INFINITY;
int mid = lo + (hi - lo) / 2;
Point2D median = pointsByX[mid];
// compute closest pair with both endpoints in left subarray or both in right subarray
double delta1 = closest(pointsByX, pointsByY, aux, lo, mid);
double delta2 = closest(pointsByX, pointsByY, aux, mid+1, hi);
double delta = Math.min(delta1, delta2);
// merge back so that pointsByY[lo..hi] are sorted by y-coordinate
merge(pointsByY, aux, lo, mid, hi);
// aux[0..m-1] = sequence of points closer than delta, sorted by y-coordinate
int m = 0;
for (int i = lo; i <= hi; i++) {
if (Math.abs(pointsByY[i].x() - median.x()) < delta)
aux[m++] = pointsByY[i];
}
// compare each point to its neighbors with y-coordinate closer than delta
for (int i = 0; i < m; i++) {
// a geometric packing argument shows that this loop iterates at most 7 times
for (int j = i+1; (j < m) && (aux[j].y() - aux[i].y() < delta); j++) {
double distance = aux[i].distanceTo(aux[j]);
if (distance < delta) {
delta = distance;
if (distance < bestDistance) {
bestDistance = delta;
best1 = aux[i];
best2 = aux[j];
// StdOut.println("better distance = " + delta + " from " + best1 + " to " + best2);
}
}
}
}
return delta;
}
/**
* Returns one of the points in the closest pair of points.
*
* @return one of the two points in the closest pair of points;
* {@code null} if no such point (because there are fewer than 2 points)
*/
public Point2D either() {
return best1;
}
/**
* Returns the other point in the closest pair of points.
*
* @return the other point in the closest pair of points
* {@code null} if no such point (because there are fewer than 2 points)
*/
public Point2D other() {
return best2;
}
/**
* Returns the Euclidean distance between the closest pair of points.
*
* @return the Euclidean distance between the closest pair of points
* {@code Double.POSITIVE_INFINITY} if no such pair of points
* exist (because there are fewer than 2 points)
*/
public double distance() {
return bestDistance;
}
// is v < w ?
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
// stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]
// precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
// copy to aux[]
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
// merge back to a[]
int i = lo, j = mid+1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++];
else if (j > hi) a[k] = aux[i++];
else if (less(aux[j], aux[i])) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
/**
* Unit tests the {@code ClosestPair} data type.
* Reads in an integer {@code n} and {@code n} points (specified by
* their x- and y-coordinates) from standard input;
* computes a closest pair of points; and prints the pair to standard
* output.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
int n = StdIn.readInt();
Point2D[] points = new Point2D[n];
for (int i = 0; i < n; i++) {
double x = StdIn.readDouble();
double y = StdIn.readDouble();
points[i] = new Point2D(x, y);
}
ClosestPair closest = new ClosestPair(points);
StdOut.println(closest.distance() + " from " + closest.either() + " to " + closest.other());
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/CollisionSystem.java
================================================
/******************************************************************************
* Compilation: javac CollisionSystem.java
* Execution: java CollisionSystem n (n random particles)
* java CollisionSystem < input.txt (from a file)
* Dependencies: StdDraw.java Particle.java MinPQ.java
* Data files: https://algs4.cs.princeton.edu/61event/diffusion.txt
* https://algs4.cs.princeton.edu/61event/diffusion2.txt
* https://algs4.cs.princeton.edu/61event/diffusion3.txt
* https://algs4.cs.princeton.edu/61event/brownian.txt
* https://algs4.cs.princeton.edu/61event/brownian2.txt
* https://algs4.cs.princeton.edu/61event/billiards5.txt
* https://algs4.cs.princeton.edu/61event/pendulum.txt
*
* Creates n random particles and simulates their motion according
* to the laws of elastic collisions.
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.awt.Color;
/**
* The {@code CollisionSystem} class represents a collection of particles
* moving in the unit box, according to the laws of elastic collision.
* This event-based simulation relies on a priority queue.
*
* For additional documentation,
* see Section 6.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class CollisionSystem {
private static final double HZ = 0.5; // number of redraw events per clock tick
private MinPQ
* This computes correct results if all arithmetic performed is
* without floating-point rounding error or arithmetic overflow.
* In practice, there will be floating-point rounding error.
*
* For additional documentation, see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Complex {
private final double re; // the real part
private final double im; // the imaginary part
/**
* Initializes a complex number from the specified real and imaginary parts.
*
* @param real the real part
* @param imag the imaginary part
*/
public Complex(double real, double imag) {
re = real;
im = imag;
}
/**
* Returns a string representation of this complex number.
*
* @return a string representation of this complex number,
* of the form 34 - 56i.
*/
public String toString() {
if (im == 0) return re + "";
if (re == 0) return im + "i";
if (im < 0) return re + " - " + (-im) + "i";
return re + " + " + im + "i";
}
/**
* Returns the absolute value of this complex number.
* This quantity is also known as the modulus or magnitude.
*
* @return the absolute value of this complex number
*/
public double abs() {
return Math.hypot(re, im);
}
/**
* Returns the phase of this complex number.
* This quantity is also known as the angle or argument.
*
* @return the phase of this complex number, a real number between -pi and pi
*/
public double phase() {
return Math.atan2(im, re);
}
/**
* Returns the sum of this complex number and the specified complex number.
*
* @param that the other complex number
* @return the complex number whose value is {@code (this + that)}
*/
public Complex plus(Complex that) {
double real = this.re + that.re;
double imag = this.im + that.im;
return new Complex(real, imag);
}
/**
* Returns the result of subtracting the specified complex number from
* this complex number.
*
* @param that the other complex number
* @return the complex number whose value is {@code (this - that)}
*/
public Complex minus(Complex that) {
double real = this.re - that.re;
double imag = this.im - that.im;
return new Complex(real, imag);
}
/**
* Returns the product of this complex number and the specified complex number.
*
* @param that the other complex number
* @return the complex number whose value is {@code (this * that)}
*/
public Complex times(Complex that) {
double real = this.re * that.re - this.im * that.im;
double imag = this.re * that.im + this.im * that.re;
return new Complex(real, imag);
}
/**
* Returns the product of this complex number and the specified scalar.
*
* @param alpha the scalar
* @return the complex number whose value is {@code (alpha * this)}
*/
public Complex scale(double alpha) {
return new Complex(alpha * re, alpha * im);
}
/**
* Returns the product of this complex number and the specified scalar.
*
* @param alpha the scalar
* @return the complex number whose value is {@code (alpha * this)}
* @deprecated Replaced by {@link #scale(double)}.
*/
@Deprecated
public Complex times(double alpha) {
return new Complex(alpha * re, alpha * im);
}
/**
* Returns the complex conjugate of this complex number.
*
* @return the complex conjugate of this complex number
*/
public Complex conjugate() {
return new Complex(re, -im);
}
/**
* Returns the reciprocal of this complex number.
*
* @return the complex number whose value is {@code (1 / this)}
*/
public Complex reciprocal() {
double scale = re*re + im*im;
return new Complex(re / scale, -im / scale);
}
/**
* Returns the real part of this complex number.
*
* @return the real part of this complex number
*/
public double re() {
return re;
}
/**
* Returns the imaginary part of this complex number.
*
* @return the imaginary part of this complex number
*/
public double im() {
return im;
}
/**
* Returns the result of dividing the specified complex number into
* this complex number.
*
* @param that the other complex number
* @return the complex number whose value is {@code (this / that)}
*/
public Complex divides(Complex that) {
return this.times(that.reciprocal());
}
/**
* Returns the complex exponential of this complex number.
*
* @return the complex exponential of this complex number
*/
public Complex exp() {
return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));
}
/**
* Returns the complex sine of this complex number.
*
* @return the complex sine of this complex number
*/
public Complex sin() {
return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im));
}
/**
* Returns the complex cosine of this complex number.
*
* @return the complex cosine of this complex number
*/
public Complex cos() {
return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im));
}
/**
* Returns the complex tangent of this complex number.
*
* @return the complex tangent of this complex number
*/
public Complex tan() {
return sin().divides(cos());
}
/**
* Unit tests the {@code Complex} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
Complex a = new Complex(5.0, 6.0);
Complex b = new Complex(-3.0, 4.0);
StdOut.println("a = " + a);
StdOut.println("b = " + b);
StdOut.println("Re(a) = " + a.re());
StdOut.println("Im(a) = " + a.im());
StdOut.println("b + a = " + b.plus(a));
StdOut.println("a - b = " + a.minus(b));
StdOut.println("a * b = " + a.times(b));
StdOut.println("b * a = " + b.times(a));
StdOut.println("a / b = " + a.divides(b));
StdOut.println("(a / b) * b = " + a.divides(b).times(b));
StdOut.println("conj(a) = " + a.conjugate());
StdOut.println("|a| = " + a.abs());
StdOut.println("tan(a) = " + a.tan());
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/Count.java
================================================
/******************************************************************************
* Compilation: javac Count.java
* Execution: java Count alpha < input.txt
* Dependencies: Alphabet.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/50strings/abra.txt
* https://algs4.cs.princeton.edu/50strings/pi.txt
*
* Create an alphabet specified on the command line, read in a
* sequence of characters over that alphabet (ignoring characters
* not in the alphabet), computes the frequency of occurrence of
* each character, and print out the results.
*
* % java Count ABCDR < abra.txt
* A 5
* B 2
* C 1
* D 1
* R 2
*
* % java Count 0123456789 < pi.txt
* 0 99959
* 1 99757
* 2 100026
* 3 100230
* 4 100230
* 5 100359
* 6 99548
* 7 99800
* 8 99985
* 9 100106
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code Count} class provides an {@link Alphabet} client for reading
* in a piece of text and computing the frequency of occurrence of each
* character over a given alphabet.
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Count {
// Do not instantiate.
private Count() { }
/**
* Reads in text from standard input; calculates the frequency of
* occurrence of each character over the alphabet specified as a
* command-line argument; and prints the frequencies to standard
* output.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
Alphabet alphabet = new Alphabet(args[0]);
final int R = alphabet.radix();
int[] count = new int[R];
while (StdIn.hasNextChar()) {
char c = StdIn.readChar();
if (alphabet.contains(c))
count[alphabet.toIndex(c)]++;
}
for (int c = 0; c < R; c++)
StdOut.println(alphabet.toChar(c) + " " + count[c]);
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/Counter.java
================================================
/******************************************************************************
* Compilation: javac Counter.java
* Execution: java Counter n trials
* Dependencies: StdRandom.java StdOut.java
*
* A mutable data type for an integer counter.
*
* The test clients create n counters and performs trials increment
* operations on random counters.
*
* java Counter 6 600000
* 100140 counter0
* 100273 counter1
* 99848 counter2
* 100129 counter3
* 99973 counter4
* 99637 counter5
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code Counter} class is a mutable data type to encapsulate a counter.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Counter implements Comparable
* 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.
* (The depth-first search part takes only O(V) time;
* however, checking for self-loops and parallel edges takes
* Θ(V + E) time in the worst case.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
*
* For additional documentation, see
* Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Cycle {
private boolean[] marked;
private int[] edgeTo;
private Stack
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Date implements Comparable
* For additional documentation, see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class DeDup {
// Do not instantiate.
private DeDup() { }
public static void main(String[] args) {
SET
* The running time is proportional to the number of individuals and
* connections in the network. If the connections are given implicitly,
* as in the movie network example (where every two actors are connected
* if they appear in the same movie), the efficiency of the algorithm
* is improved by allowing both movie and actor vertices and connecting
* each movie to all of the actors that appear in that movie.
*
* For additional documentation,
* see Section 4.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class DegreesOfSeparation {
// this class cannot be instantiated
private DegreesOfSeparation() { }
/**
* Reads in a social network from a file, and then repeatedly reads in
* individuals from standard input and prints out their degrees of
* separation.
* Takes three command-line arguments: the name of a file,
* a delimiter, and the name of the distinguished individual.
* Each line in the file contains the name of a vertex, followed by a
* list of the names of the vertices adjacent to that vertex,
* separated by the delimiter.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
String filename = args[0];
String delimiter = args[1];
String source = args[2];
// StdOut.println("Source: " + source);
SymbolGraph sg = new SymbolGraph(filename, delimiter);
Graph graph = sg.graph();
if (!sg.contains(source)) {
StdOut.println(source + " not in database.");
return;
}
int s = sg.indexOf(source);
BreadthFirstPaths bfs = new BreadthFirstPaths(graph, s);
while (!StdIn.isEmpty()) {
String sink = StdIn.readLine();
if (sg.contains(sink)) {
int t = sg.indexOf(sink);
if (bfs.hasPathTo(t)) {
for (int v : bfs.pathTo(t)) {
StdOut.println(" " + sg.nameOf(v));
}
}
else {
StdOut.println("Not connected");
}
}
else {
StdOut.println(" Not in database.");
}
}
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/DepthFirstDirectedPaths.java
================================================
/******************************************************************************
* Compilation: javac DepthFirstDirectedPaths.java
* Execution: java DepthFirstDirectedPaths digraph.txt s
* Dependencies: Digraph.java Stack.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Determine reachability in a digraph from a given vertex using
* depth-first search.
* Runs in O(E + V) time.
*
* % java DepthFirstDirectedPaths tinyDG.txt 3
* 3 to 0: 3-5-4-2-0
* 3 to 1: 3-5-4-2-0-1
* 3 to 2: 3-5-4-2
* 3 to 3: 3
* 3 to 4: 3-5-4
* 3 to 5: 3-5
* 3 to 6: not connected
* 3 to 7: not connected
* 3 to 8: not connected
* 3 to 9: not connected
* 3 to 10: not connected
* 3 to 11: not connected
* 3 to 12: not connected
*
******************************************************************************/
package edu.princeton.cs.algs4;
/**
* The {@code DepthFirstDirectedPaths} class represents a data type for
* finding directed paths from a source vertex s to every
* other vertex in the digraph.
*
* 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).
*
* 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 DepthFirstDirectedPaths {
private boolean[] marked; // marked[v] = true iff v is reachable from s
private int[] edgeTo; // edgeTo[v] = last edge on path from s to v
private final int s; // source vertex
/**
* Computes a directed path from {@code s} to every other vertex in {@code digraph}.
* @param digraph the digraph
* @param s the source vertex
* @throws IllegalArgumentException unless {@code 0 <= s < V}
*/
public DepthFirstDirectedPaths(Digraph digraph, int s) {
marked = new boolean[digraph.V()];
edgeTo = new int[digraph.V()];
this.s = s;
validateVertex(s);
dfs(digraph, s);
}
private void dfs(Digraph digraph, int v) {
marked[v] = true;
for (int w : digraph.adj(v)) {
if (!marked[w]) {
edgeTo[w] = v;
dfs(digraph, w);
}
}
}
/**
* Is there a directed path from the source vertex {@code s} to vertex {@code v}?
* @param v the vertex
* @return {@code true} if there is a directed path from the source
* vertex {@code s} to vertex {@code v}, {@code false} otherwise
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public boolean hasPathTo(int v) {
validateVertex(v);
return marked[v];
}
/**
* Returns a directed path from the source vertex {@code s} to vertex {@code v}, or
* {@code null} if no such path.
* @param v the vertex
* @return the sequence of vertices on a directed path from the source vertex
* {@code s} to vertex {@code v}, as an Iterable
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public Iterable
* This implementation uses depth-first search.
* Each constructor takes Θ(V + E) time,
* 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).
*
* 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 DepthFirstOrder {
private boolean[] marked; // marked[v] = has v been marked in dfs?
private int[] pre; // pre[v] = preorder number of v
private int[] post; // post[v] = postorder number of v
private Queue
* 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 graph).
*
* For additional documentation, see
* Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class DepthFirstPaths {
private boolean[] marked; // marked[v] = is there an s-v path?
private int[] edgeTo; // edgeTo[v] = last edge on s-v path
private final int s; // source vertex
/**
* Computes a path between {@code s} and every other vertex in {@code graph}.
* @param graph the graph
* @param s the source vertex
* @throws IllegalArgumentException unless {@code 0 <= s < V}
*/
public DepthFirstPaths(Graph graph, int s) {
this.s = s;
edgeTo = new int[graph.V()];
marked = new boolean[graph.V()];
validateVertex(s);
dfs(graph, s);
}
// depth first search from v
private void dfs(Graph graph, int v) {
marked[v] = true;
for (int w : graph.adj(v)) {
if (!marked[w]) {
edgeTo[w] = v;
dfs(graph, w);
}
}
}
/**
* Is there a path between the source vertex {@code s} and vertex {@code v}?
* @param v the vertex
* @return {@code true} if there is a path, {@code false} otherwise
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public boolean hasPathTo(int v) {
validateVertex(v);
return marked[v];
}
/**
* Returns a path between the source vertex {@code s} and vertex {@code v}, or
* {@code null} if no such path.
* @param v the vertex
* @return the sequence of vertices on a path between the source vertex
* {@code s} and vertex {@code v}, as an Iterable
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public Iterable
* This implementation uses depth-first search.
* See {@link NonrecursiveDFS} for a non-recursive version.
* 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 graph).
*
* For additional documentation, see
* Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class DepthFirstSearch {
private boolean[] marked; // marked[v] = is there an s-v path?
private int count; // number of vertices connected to s
/**
* Computes the vertices in {@code graph} that are
* connected to the source vertex {@code s}.
* @param graph the graph
* @param s the source vertex
* @throws IllegalArgumentException unless {@code 0 <= s < V}
*/
public DepthFirstSearch(Graph graph, int s) {
marked = new boolean[graph.V()];
validateVertex(s);
dfs(graph, s);
}
// depth first search from v
private void dfs(Graph graph, int v) {
count++;
marked[v] = true;
for (int w : graph.adj(v)) {
if (!marked[w]) {
dfs(graph, w);
}
}
}
/**
* Is there a path between the source vertex {@code s} and vertex {@code v}?
* @param v the vertex
* @return {@code true} if there is a path, {@code false} otherwise
* @throws IllegalArgumentException unless {@code 0 <= v < V}
*/
public boolean marked(int v) {
validateVertex(v);
return marked[v];
}
/**
* Returns the number of vertices connected to the source vertex {@code s}.
* @return the number of vertices connected to the source vertex {@code s}
*/
public int count() {
return count;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private void validateVertex(int v) {
int V = marked.length;
if (v < 0 || v >= V)
throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
}
/**
* Unit tests the {@code DepthFirstSearch} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
In in = new In(args[0]);
Graph graph = new Graph(in);
int s = Integer.parseInt(args[1]);
DepthFirstSearch search = new DepthFirstSearch(graph, s);
for (int v = 0; v < graph.V(); v++) {
if (search.marked(v))
StdOut.print(v + " ");
}
StdOut.println();
if (search.count() != graph.V()) StdOut.println("NOT connected");
else StdOut.println("connected");
}
}
/******************************************************************************
* Copyright 2002-2025, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
================================================
FILE: src/main/java/edu/princeton/cs/algs4/Digraph.java
================================================
/******************************************************************************
* Compilation: javac Digraph.java
* Execution: java Digraph filename.txt
* Dependencies: Bag.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* A graph, implemented using an array of lists.
* Parallel edges and self-loops are permitted.
*
* % java Digraph tinyDG.txt
* 13 vertices, 22 edges
* 0: 5 1
* 1:
* 2: 0 3
* 3: 5 2
* 4: 3 2
* 5: 4
* 6: 9 4 8 0
* 7: 6 9
* 8: 6
* 9: 11 10
* 10: 12
* 11: 4 12
* 12: 9
*
******************************************************************************/
package edu.princeton.cs.algs4;
import java.util.NoSuchElementException;
/**
* The {@code Digraph} class represents a directed graph of vertices
* named 0 through V - 1.
* It supports the following two primary operations: add an edge to the digraph,
* iterate over all of the vertices adjacent 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,
* the number of edges E in the digraph, and the reverse 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.
* The
* 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 Digraph {
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
* 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 DigraphGenerator {
private static final class Edge implements ComparableBinaryIn data type provides methods for reading
* in bits from a binary input stream. It can process the bits
* one bit at a time (as a {@code boolean}),
* 8 bits at a time (as a {@code byte} or {@code char}),
* 16 bits at a time (as a {@code short}),
* 32 bits at a time (as an {@code int} or {@code float}), or
* 64 bits at a time (as a {@code double} or {@code long}).
* BinaryOut data type provides a basic capability for
* converting primitive type variables ({@code boolean}, {@code byte},
* {@code char}, {@code int}, {@code long}, {@code float}, and {@code double})
* to sequences of bits and writing them to an output stream.
* The output stream can be standard output, a file, an OutputStream or a Socket.
* Uses big-endian (most-significant byte first).
* BinaryStdIn class provides static methods for reading
* in bits from standard input. It can process the bits
* one bit at a time (as a {@code boolean}),
* 8 bits at a time (as a {@code byte} or {@code char}),
* 16 bits at a time (as a {@code short}), 32 bits at a time
* (as an {@code int} or {@code float}), or 64 bits at a time (as a
* {@code double} or {@code long}).
* BinaryStdOut class provides static methods for converting
* primitive type variables ({@code boolean}, {@code byte}, {@code char},
* {@code int}, {@code long}, {@code float}, and {@code double})
* to sequences of bits and writing them to standard output.
* Uses big-endian (most-significant byte first).
* reverse() method takes Θ(E + V) time
* and space; all other instance methods take Θ(1) time. (Though, iterating over
* the vertices returned by {@link #adj(int)} takes time proportional
* to the outdegree of the vertex.)
* Constructing an empty digraph with V vertices takes
* Θ(V) time; constructing a digraph with E edges
* and V vertices takes Θ(E + V) time.
*