├── Non-Comment版本 ├── nonComment-2.7 heapsort.java ├── nonComment-2.3 shellsort.java ├── nonComment-1.4 multiset (linked list).java ├── nonComment-4.5 topological order in a DAG.java ├── nonComment-1.5 weighted quick union.java ├── nonComment-5.11 data compression (Lempel–Ziv–Welch).java ├── nonComment-4.1 paths in a graph (DFS).java ├── nonComment-4.4 depth-first search in a digraph.java ├── nonComment-5.3 three-way string quicksort.java ├── nonComment-5.1 LSD radix sort.java ├── nonComment-2.2 selection sort.java ├── nonComment-1.1 LIFO stack (resizing array).java ├── nonComment-5.8 substring search (Rabin–Karp).java ├── nonComment-4.6 strong components (Kosaraju–Sharir).java ├── nonComment-4.10 shortest paths in a DAG.java ├── nonComment-5.6 substring search (Knuth–Morris–Pratt).java ├── nonComment-3.1 sequential search.java ├── nonComment-5.9 NFA for regular expressions.java ├── nonComment-2.5 quicksort.java ├── nonComment-5.7 substring search (Boyer–Moore).java ├── nonComment-4.8 MST (Kruskal).java ├── nonComment-4.3 connected components of a graph.java ├── nonComment-3.5 separate chaining hash table.java ├── nonComment-2.4 top-down mergesort.java ├── nonComment-1.2 LIFO stack (linked list).java ├── nonComment-2.1 insertion sort.java ├── nonComment-1.3 FIFO queue (linked list).java ├── nonComment-6.3 suffix array (suffix sorting).java ├── nonComment-4.7 MST (Prim).java ├── nonComment-3.6 linear probing hash table.java ├── nonComment-5.10 data compression (Huffman).java ├── nonComment-5.2 MSD radix sort.java ├── nonComment-4.9 shortest paths (Dijkstra).java ├── nonComment-6.1 collision system.java ├── nonComment-2.6 max heap priority queue.java ├── nonComment-4.2 paths in a graph (BFS).java ├── nonComment-5.4 multiway trie symbol table.java └── nonComment-6.4 maxflow–mincut.java ├── Chapter 2 排序 Sorting ├── 2.7 heapsort.java ├── 2.3 shellsort.java ├── 2.2 selection sort.java ├── 2.5 quicksort.java └── 2.4 top-down mergesort.java ├── chapter 1 基础 Fundamental ├── 1.4 multiset (linked list).java ├── 1.1 LIFO stack (resizing array).java └── 1.2 LIFO stack (linked list).java ├── Chapter 5 字符串 Strings ├── 5.11 data compression (Lempel–Ziv–Welch).java ├── 5.3 three-way string quicksort.java ├── 5.1 LSD radix sort.java ├── 5.8 substring search (Rabin–Karp).java ├── 5.7 substring search (Boyer–Moore).java ├── 5.6 substring search (Knuth–Morris–Pratt).java └── 5.9 NFA for regular expressions.java └── Chapter 4 图 Graph ├── 4.1 paths in a graph (DFS).java ├── 4.4 depth-first search in a digraph.java ├── 4.5 topological order in a DAG.java ├── 4.10 shortest paths in a DAG.java ├── 4.6 strong components (Kosaraju–Sharir).java └── 4.8 MST (Kruskal).java /Non-Comment版本/nonComment-2.7 heapsort.java: -------------------------------------------------------------------------------- 1 | public class Heap { 2 | 3 | private Heap() { } 4 | 5 | public static void sort(Comparable[] pq) { 6 | int n = pq.length; 7 | for (int k = n/2; k >= 1; k--) 8 | sink(pq, k, n); 9 | while (n > 1) { 10 | exch(pq, 1, n--); 11 | sink(pq, 1, n); 12 | } 13 | } 14 | 15 | 16 | private static void sink(Comparable[] pq, int k, int n) { 17 | while (2*k <= n) { 18 | int j = 2*k; 19 | if (j < n && less(pq, j, j+1)) j++; 20 | if (!less(pq, k, j)) break; 21 | exch(pq, k, j); 22 | k = j; 23 | } 24 | } 25 | 26 | private static boolean less(Comparable[] pq, int i, int j) { 27 | return pq[i-1].compareTo(pq[j-1]) < 0; 28 | } 29 | 30 | private static void exch(Object[] pq, int i, int j) { 31 | Object swap = pq[i-1]; 32 | pq[i-1] = pq[j-1]; 33 | pq[j-1] = swap; 34 | } 35 | 36 | private static void show(Comparable[] a) { 37 | for (int i = 0; i < a.length; i++) { 38 | StdOut.println(a[i]); 39 | } 40 | } 41 | 42 | public static void main(String[] args) { 43 | String[] a = StdIn.readAllStrings(); 44 | Heap.sort(a); 45 | show(a); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-2.3 shellsort.java: -------------------------------------------------------------------------------- 1 | public class Shell { 2 | 3 | private Shell() { } 4 | 5 | public static void sort(Comparable[] a) { 6 | int n = a.length; 7 | 8 | int h = 1; 9 | while (h < n/3) h = 3*h + 1; 10 | 11 | while (h >= 1) { 12 | for (int i = h; i < n; i++) { 13 | for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) { 14 | exch(a, j, j-h); 15 | } 16 | } 17 | assert isHsorted(a, h); 18 | h /= 3; 19 | } 20 | assert isSorted(a); 21 | } 22 | 23 | 24 | 25 | 26 | private static boolean less(Comparable v, Comparable w) { 27 | return v.compareTo(w) < 0; 28 | } 29 | 30 | private static void exch(Object[] a, int i, int j) { 31 | Object swap = a[i]; 32 | a[i] = a[j]; 33 | a[j] = swap; 34 | } 35 | 36 | 37 | private static boolean isSorted(Comparable[] a) { 38 | for (int i = 1; i < a.length; i++) 39 | if (less(a[i], a[i-1])) return false; 40 | return true; 41 | } 42 | 43 | private static boolean isHsorted(Comparable[] a, int h) { 44 | for (int i = h; i < a.length; i++) 45 | if (less(a[i], a[i-h])) return false; 46 | return true; 47 | } 48 | 49 | private static void show(Comparable[] a) { 50 | for (int i = 0; i < a.length; i++) { 51 | StdOut.println(a[i]); 52 | } 53 | } 54 | 55 | public static void main(String[] args) { 56 | String[] a = StdIn.readAllStrings(); 57 | Shell.sort(a); 58 | show(a); 59 | } 60 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-1.4 multiset (linked list).java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.NoSuchElementException; 3 | 4 | public class LinkedBag implements Iterable { 5 | private Node first; 6 | private int n; 7 | 8 | private class Node { 9 | private Item item; 10 | private Node next; 11 | } 12 | 13 | public LinkedBag() { 14 | first = null; 15 | n = 0; 16 | } 17 | 18 | public boolean isEmpty() { 19 | return first == null; 20 | } 21 | 22 | public int size() { 23 | return n; 24 | } 25 | 26 | public void add(Item item) { 27 | Node oldfirst = first; 28 | first = new Node(); 29 | first.item = item; 30 | first.next = oldfirst; 31 | n++; 32 | } 33 | 34 | 35 | public Iterator iterator() { 36 | return new ListIterator(); 37 | } 38 | 39 | private class ListIterator implements Iterator { 40 | private Node current = first; 41 | 42 | public boolean hasNext() { return current != null; } 43 | public void remove() { throw new UnsupportedOperationException(); } 44 | 45 | public Item next() { 46 | if (!hasNext()) throw new NoSuchElementException(); 47 | Item item = current.item; 48 | current = current.next; 49 | return item; 50 | } 51 | } 52 | 53 | public static void main(String[] args) { 54 | LinkedBag bag = new LinkedBag(); 55 | while (!StdIn.isEmpty()) { 56 | String item = StdIn.readString(); 57 | bag.add(item); 58 | } 59 | 60 | StdOut.println("size of bag = " + bag.size()); 61 | for (String s : bag) { 62 | StdOut.println(s); 63 | } 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.5 topological order in a DAG.java: -------------------------------------------------------------------------------- 1 | 2 | public class Topological { 3 | private Iterable order; 4 | private int[] rank; 5 | 6 | public Topological(Digraph G) { 7 | DirectedCycle finder = new DirectedCycle(G); 8 | if (!finder.hasCycle()) { 9 | DepthFirstOrder dfs = new DepthFirstOrder(G); 10 | order = dfs.reversePost(); 11 | rank = new int[G.V()]; 12 | int i = 0; 13 | for (int v : order) 14 | rank[v] = i++; 15 | } 16 | } 17 | 18 | public Topological(EdgeWeightedDigraph G) { 19 | EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(G); 20 | if (!finder.hasCycle()) { 21 | DepthFirstOrder dfs = new DepthFirstOrder(G); 22 | order = dfs.reversePost(); 23 | } 24 | } 25 | 26 | public Iterable order() { 27 | return order; 28 | } 29 | 30 | public boolean hasOrder() { 31 | return order != null; 32 | } 33 | 34 | @Deprecated 35 | public boolean isDAG() { 36 | return hasOrder(); 37 | } 38 | 39 | public int rank(int v) { 40 | validateVertex(v); 41 | if (hasOrder()) return rank[v]; 42 | else return -1; 43 | } 44 | 45 | private void validateVertex(int v) { 46 | int V = rank.length; 47 | if (v < 0 || v >= V) 48 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 49 | } 50 | 51 | public static void main(String[] args) { 52 | String filename = args[0]; 53 | String delimiter = args[1]; 54 | SymbolDigraph sg = new SymbolDigraph(filename, delimiter); 55 | Topological topological = new Topological(sg.digraph()); 56 | for (int v : topological.order()) { 57 | StdOut.println(sg.nameOf(v)); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-1.5 weighted quick union.java: -------------------------------------------------------------------------------- 1 | public class WeightedQuickUnionUF { 2 | private int[] parent; 3 | private int[] size; 4 | private int count; 5 | 6 | public WeightedQuickUnionUF(int n) { 7 | count = n; 8 | parent = new int[n]; 9 | size = new int[n]; 10 | for (int i = 0; i < n; i++) { 11 | parent[i] = i; 12 | size[i] = 1; 13 | } 14 | } 15 | 16 | public int count() { 17 | return count; 18 | } 19 | 20 | public int find(int p) { 21 | validate(p); 22 | while (p != parent[p]) 23 | p = parent[p]; 24 | return p; 25 | } 26 | 27 | private void validate(int p) { 28 | int n = parent.length; 29 | if (p < 0 || p >= n) { 30 | throw new IndexOutOfBoundsException("index " + p + " is not between 0 and " + (n-1)); 31 | } 32 | } 33 | 34 | public boolean connected(int p, int q) { 35 | return find(p) == find(q); 36 | } 37 | 38 | public void union(int p, int q) { 39 | int rootP = find(p); 40 | int rootQ = find(q); 41 | if (rootP == rootQ) return; 42 | 43 | if (size[rootP] < size[rootQ]) { 44 | parent[rootP] = rootQ; 45 | size[rootQ] += size[rootP]; 46 | } 47 | else { 48 | parent[rootQ] = rootP; 49 | size[rootP] += size[rootQ]; 50 | } 51 | count--; 52 | } 53 | 54 | 55 | public static void main(String[] args) { 56 | int n = StdIn.readInt(); 57 | WeightedQuickUnionUF uf = new WeightedQuickUnionUF(n); 58 | while (!StdIn.isEmpty()) { 59 | int p = StdIn.readInt(); 60 | int q = StdIn.readInt(); 61 | if (uf.connected(p, q)) continue; 62 | uf.union(p, q); 63 | StdOut.println(p + " " + q); 64 | } 65 | StdOut.println(uf.count() + " components"); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.11 data compression (Lempel–Ziv–Welch).java: -------------------------------------------------------------------------------- 1 | public class LZW { 2 | private static final int R = 256; 3 | private static final int L = 4096; 4 | private static final int W = 12; 5 | 6 | private LZW() { } 7 | 8 | public static void compress() { 9 | String input = BinaryStdIn.readString(); 10 | TST st = new TST(); 11 | for (int i = 0; i < R; i++) 12 | st.put("" + (char) i, i); 13 | int code = R+1; 14 | 15 | while (input.length() > 0) { 16 | String s = st.longestPrefixOf(input); 17 | BinaryStdOut.write(st.get(s), W); 18 | int t = s.length(); 19 | if (t < input.length() && code < L) 20 | st.put(input.substring(0, t + 1), code++); 21 | input = input.substring(t); 22 | } 23 | BinaryStdOut.write(R, W); 24 | BinaryStdOut.close(); 25 | } 26 | 27 | public static void expand() { 28 | String[] st = new String[L]; 29 | int i; 30 | 31 | for (i = 0; i < R; i++) 32 | st[i] = "" + (char) i; 33 | st[i++] = ""; 34 | 35 | int codeword = BinaryStdIn.readInt(W); 36 | if (codeword == R) return; 37 | String val = st[codeword]; 38 | 39 | while (true) { 40 | BinaryStdOut.write(val); 41 | codeword = BinaryStdIn.readInt(W); 42 | if (codeword == R) break; 43 | String s = st[codeword]; 44 | if (i == codeword) s = val + val.charAt(0); 45 | if (i < L) st[i++] = val + s.charAt(0); 46 | val = s; 47 | } 48 | BinaryStdOut.close(); 49 | } 50 | 51 | public static void main(String[] args) { 52 | if (args[0].equals("-")) compress(); 53 | else if (args[0].equals("+")) expand(); 54 | else throw new IllegalArgumentException("Illegal command line argument"); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.1 paths in a graph (DFS).java: -------------------------------------------------------------------------------- 1 | public class DepthFirstPaths { 2 | private boolean[] marked; 3 | private int[] edgeTo; 4 | private final int s; 5 | 6 | public DepthFirstPaths(Graph G, int s) { 7 | this.s = s; 8 | edgeTo = new int[G.V()]; 9 | marked = new boolean[G.V()]; 10 | validateVertex(s); 11 | dfs(G, s); 12 | } 13 | 14 | private void dfs(Graph G, int v) { 15 | marked[v] = true; 16 | for (int w : G.adj(v)) { 17 | if (!marked[w]) { 18 | edgeTo[w] = v; 19 | dfs(G, w); 20 | } 21 | } 22 | } 23 | 24 | public boolean hasPathTo(int v) { 25 | validateVertex(v); 26 | return marked[v]; 27 | } 28 | 29 | public Iterable pathTo(int v) { 30 | validateVertex(v); 31 | if (!hasPathTo(v)) return null; 32 | Stack path = new Stack(); 33 | for (int x = v; x != s; x = edgeTo[x]) 34 | path.push(x); 35 | path.push(s); 36 | return path; 37 | } 38 | 39 | private void validateVertex(int v) { 40 | int V = marked.length; 41 | if (v < 0 || v >= V) 42 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 43 | } 44 | 45 | public static void main(String[] args) { 46 | In in = new In(args[0]); 47 | Graph G = new Graph(in); 48 | int s = Integer.parseInt(args[1]); 49 | DepthFirstPaths dfs = new DepthFirstPaths(G, s); 50 | 51 | for (int v = 0; v < G.V(); v++) { 52 | if (dfs.hasPathTo(v)) { 53 | StdOut.printf("%d to %d: ", s, v); 54 | for (int x : dfs.pathTo(v)) { 55 | if (x == s) StdOut.print(x); 56 | else StdOut.print("-" + x); 57 | } 58 | StdOut.println(); 59 | } 60 | 61 | else { 62 | StdOut.printf("%d to %d: not connected\n", s, v); 63 | } 64 | 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.4 depth-first search in a digraph.java: -------------------------------------------------------------------------------- 1 | public class DirectedDFS { 2 | private boolean[] marked; 3 | private int count; 4 | 5 | public DirectedDFS(Digraph G, int s) { 6 | marked = new boolean[G.V()]; 7 | validateVertex(s); 8 | dfs(G, s); 9 | } 10 | 11 | public DirectedDFS(Digraph G, Iterable sources) { 12 | marked = new boolean[G.V()]; 13 | validateVertices(sources); 14 | for (int v : sources) { 15 | if (!marked[v]) dfs(G, v); 16 | } 17 | } 18 | 19 | private void dfs(Digraph G, int v) { 20 | count++; 21 | marked[v] = true; 22 | for (int w : G.adj(v)) { 23 | if (!marked[w]) dfs(G, w); 24 | } 25 | } 26 | 27 | public boolean marked(int v) { 28 | validateVertex(v); 29 | return marked[v]; 30 | } 31 | 32 | public int count() { 33 | return count; 34 | } 35 | 36 | private void validateVertex(int v) { 37 | int V = marked.length; 38 | if (v < 0 || v >= V) 39 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 40 | } 41 | 42 | private void validateVertices(Iterable vertices) { 43 | if (vertices == null) { 44 | throw new IllegalArgumentException("argument is null"); 45 | } 46 | int V = marked.length; 47 | for (int v : vertices) { 48 | if (v < 0 || v >= V) { 49 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 50 | } 51 | } 52 | } 53 | 54 | 55 | public static void main(String[] args) { 56 | 57 | In in = new In(args[0]); 58 | Digraph G = new Digraph(in); 59 | 60 | Bag sources = new Bag(); 61 | for (int i = 1; i < args.length; i++) { 62 | int s = Integer.parseInt(args[i]); 63 | sources.add(s); 64 | } 65 | 66 | DirectedDFS dfs = new DirectedDFS(G, sources); 67 | 68 | for (int v = 0; v < G.V(); v++) { 69 | if (dfs.marked(v)) StdOut.print(v + " "); 70 | } 71 | StdOut.println(); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /Chapter 2 排序 Sorting/2.7 heapsort.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code Heap} class provides a static methods for heapsorting 3 | * an array. 4 | * @author Robert Sedgewick 5 | * @author Kevin Wayne 6 | */ 7 | public class Heap { 8 | 9 | // This class should not be instantiated. 10 | private Heap() { } 11 | 12 | /** 13 | * Rearranges the array in ascending order, using the natural order. 14 | * @param pq the array to be sorted 15 | */ 16 | public static void sort(Comparable[] pq) { 17 | int n = pq.length; 18 | for (int k = n/2; k >= 1; k--) 19 | sink(pq, k, n); 20 | while (n > 1) { 21 | exch(pq, 1, n--); 22 | sink(pq, 1, n); 23 | } 24 | } 25 | 26 | /*************************************************************************** 27 | * Helper functions to restore the heap invariant. 28 | ***************************************************************************/ 29 | 30 | private static void sink(Comparable[] pq, int k, int n) { 31 | while (2*k <= n) { 32 | int j = 2*k; 33 | if (j < n && less(pq, j, j+1)) j++; 34 | if (!less(pq, k, j)) break; 35 | exch(pq, k, j); 36 | k = j; 37 | } 38 | } 39 | 40 | /*************************************************************************** 41 | * Helper functions for comparisons and swaps. 42 | * Indices are "off-by-one" to support 1-based indexing. 43 | ***************************************************************************/ 44 | private static boolean less(Comparable[] pq, int i, int j) { 45 | return pq[i-1].compareTo(pq[j-1]) < 0; 46 | } 47 | 48 | private static void exch(Object[] pq, int i, int j) { 49 | Object swap = pq[i-1]; 50 | pq[i-1] = pq[j-1]; 51 | pq[j-1] = swap; 52 | } 53 | 54 | // print array to standard output 55 | private static void show(Comparable[] a) { 56 | for (int i = 0; i < a.length; i++) { 57 | StdOut.println(a[i]); 58 | } 59 | } 60 | 61 | /** 62 | * Reads in a sequence of strings from standard input; heapsorts them; 63 | * and prints them to standard output in ascending order. 64 | * 65 | * @param args the command-line arguments 66 | */ 67 | public static void main(String[] args) { 68 | String[] a = StdIn.readAllStrings(); 69 | Heap.sort(a); 70 | show(a); 71 | } 72 | } -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.3 three-way string quicksort.java: -------------------------------------------------------------------------------- 1 | public class Quick3string { 2 | private static final int CUTOFF = 15; 3 | 4 | private Quick3string() { } 5 | 6 | public static void sort(String[] a) { 7 | StdRandom.shuffle(a); 8 | sort(a, 0, a.length-1, 0); 9 | assert isSorted(a); 10 | } 11 | 12 | private static int charAt(String s, int d) { 13 | assert d >= 0 && d <= s.length(); 14 | if (d == s.length()) return -1; 15 | return s.charAt(d); 16 | } 17 | 18 | 19 | private static void sort(String[] a, int lo, int hi, int d) { 20 | 21 | if (hi <= lo + CUTOFF) { 22 | insertion(a, lo, hi, d); 23 | return; 24 | } 25 | 26 | int lt = lo, gt = hi; 27 | int v = charAt(a[lo], d); 28 | int i = lo + 1; 29 | while (i <= gt) { 30 | int t = charAt(a[i], d); 31 | if (t < v) exch(a, lt++, i++); 32 | else if (t > v) exch(a, i, gt--); 33 | else i++; 34 | } 35 | 36 | sort(a, lo, lt-1, d); 37 | if (v >= 0) sort(a, lt, gt, d+1); 38 | sort(a, gt+1, hi, d); 39 | } 40 | 41 | private static void insertion(String[] a, int lo, int hi, int d) { 42 | for (int i = lo; i <= hi; i++) 43 | for (int j = i; j > lo && less(a[j], a[j-1], d); j--) 44 | exch(a, j, j-1); 45 | } 46 | 47 | private static void exch(String[] a, int i, int j) { 48 | String temp = a[i]; 49 | a[i] = a[j]; 50 | a[j] = temp; 51 | } 52 | 53 | 54 | private static boolean less(String v, String w, int d) { 55 | assert v.substring(0, d).equals(w.substring(0, d)); 56 | for (int i = d; i < Math.min(v.length(), w.length()); i++) { 57 | if (v.charAt(i) < w.charAt(i)) return true; 58 | if (v.charAt(i) > w.charAt(i)) return false; 59 | } 60 | return v.length() < w.length(); 61 | } 62 | 63 | private static boolean isSorted(String[] a) { 64 | for (int i = 1; i < a.length; i++) 65 | if (a[i].compareTo(a[i-1]) < 0) return false; 66 | return true; 67 | } 68 | 69 | 70 | public static void main(String[] args) { 71 | 72 | String[] a = StdIn.readAllStrings(); 73 | int n = a.length; 74 | 75 | sort(a); 76 | 77 | for (int i = 0; i < n; i++) 78 | StdOut.println(a[i]); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.1 LSD radix sort.java: -------------------------------------------------------------------------------- 1 | public class LSD { 2 | private static final int BITS_PER_BYTE = 8; 3 | 4 | private LSD() { } 5 | 6 | public static void sort(String[] a, int w) { 7 | int n = a.length; 8 | int R = 256; 9 | String[] aux = new String[n]; 10 | 11 | for (int d = w-1; d >= 0; d--) { 12 | 13 | int[] count = new int[R+1]; 14 | for (int i = 0; i < n; i++) 15 | count[a[i].charAt(d) + 1]++; 16 | 17 | for (int r = 0; r < R; r++) 18 | count[r+1] += count[r]; 19 | 20 | for (int i = 0; i < n; i++) 21 | aux[count[a[i].charAt(d)]++] = a[i]; 22 | 23 | for (int i = 0; i < n; i++) 24 | a[i] = aux[i]; 25 | } 26 | } 27 | 28 | public static void sort(int[] a) { 29 | final int BITS = 32; 30 | final int R = 1 << BITS_PER_BYTE; 31 | final int MASK = R - 1; 32 | final int w = BITS / BITS_PER_BYTE; 33 | 34 | int n = a.length; 35 | int[] aux = new int[n]; 36 | 37 | for (int d = 0; d < w; d++) { 38 | 39 | int[] count = new int[R+1]; 40 | for (int i = 0; i < n; i++) { 41 | int c = (a[i] >> BITS_PER_BYTE*d) & MASK; 42 | count[c + 1]++; 43 | } 44 | 45 | for (int r = 0; r < R; r++) 46 | count[r+1] += count[r]; 47 | 48 | if (d == w-1) { 49 | int shift1 = count[R] - count[R/2]; 50 | int shift2 = count[R/2]; 51 | for (int r = 0; r < R/2; r++) 52 | count[r] += shift1; 53 | for (int r = R/2; r < R; r++) 54 | count[r] -= shift2; 55 | } 56 | 57 | for (int i = 0; i < n; i++) { 58 | int c = (a[i] >> BITS_PER_BYTE*d) & MASK; 59 | aux[count[c]++] = a[i]; 60 | } 61 | 62 | for (int i = 0; i < n; i++) 63 | a[i] = aux[i]; 64 | } 65 | } 66 | 67 | public static void main(String[] args) { 68 | String[] a = StdIn.readAllStrings(); 69 | int n = a.length; 70 | 71 | int w = a[0].length(); 72 | for (int i = 0; i < n; i++) 73 | assert a[i].length() == w : "Strings must have fixed length"; 74 | 75 | sort(a, w); 76 | 77 | for (int i = 0; i < n; i++) 78 | StdOut.println(a[i]); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-2.2 selection sort.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | public class Selection { 4 | 5 | private Selection() { } 6 | 7 | public static void sort(Comparable[] a) { 8 | int n = a.length; 9 | for (int i = 0; i < n; i++) { 10 | int min = i; 11 | for (int j = i+1; j < n; j++) { 12 | if (less(a[j], a[min])) min = j; 13 | } 14 | exch(a, i, min); 15 | assert isSorted(a, 0, i); 16 | } 17 | assert isSorted(a); 18 | } 19 | 20 | public static void sort(Object[] a, Comparator comparator) { 21 | int n = a.length; 22 | for (int i = 0; i < n; i++) { 23 | int min = i; 24 | for (int j = i+1; j < n; j++) { 25 | if (less(comparator, a[j], a[min])) min = j; 26 | } 27 | exch(a, i, min); 28 | assert isSorted(a, comparator, 0, i); 29 | } 30 | assert isSorted(a, comparator); 31 | } 32 | 33 | 34 | 35 | private static boolean less(Comparable v, Comparable w) { 36 | return v.compareTo(w) < 0; 37 | } 38 | 39 | private static boolean less(Comparator comparator, Object v, Object w) { 40 | return comparator.compare(v, w) < 0; 41 | } 42 | 43 | 44 | private static void exch(Object[] a, int i, int j) { 45 | Object swap = a[i]; 46 | a[i] = a[j]; 47 | a[j] = swap; 48 | } 49 | 50 | 51 | 52 | private static boolean isSorted(Comparable[] a) { 53 | return isSorted(a, 0, a.length - 1); 54 | } 55 | 56 | private static boolean isSorted(Comparable[] a, int lo, int hi) { 57 | for (int i = lo + 1; i <= hi; i++) 58 | if (less(a[i], a[i-1])) return false; 59 | return true; 60 | } 61 | 62 | private static boolean isSorted(Object[] a, Comparator comparator) { 63 | return isSorted(a, comparator, 0, a.length - 1); 64 | } 65 | 66 | private static boolean isSorted(Object[] a, Comparator comparator, int lo, int hi) { 67 | for (int i = lo + 1; i <= hi; i++) 68 | if (less(comparator, a[i], a[i-1])) return false; 69 | return true; 70 | } 71 | 72 | 73 | 74 | private static void show(Comparable[] a) { 75 | for (int i = 0; i < a.length; i++) { 76 | StdOut.println(a[i]); 77 | } 78 | } 79 | 80 | public static void main(String[] args) { 81 | String[] a = StdIn.readAllStrings(); 82 | Selection.sort(a); 83 | show(a); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-1.1 LIFO stack (resizing array).java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.NoSuchElementException; 3 | public class ResizingArrayStack implements Iterable { 4 | private Item[] a; 5 | private int n; 6 | 7 | 8 | public ResizingArrayStack() { 9 | a = (Item[]) new Object[2]; 10 | n = 0; 11 | } 12 | 13 | public boolean isEmpty() { 14 | return n == 0; 15 | } 16 | 17 | public int size() { 18 | return n; 19 | } 20 | 21 | 22 | private void resize(int capacity) { 23 | assert capacity >= n; 24 | 25 | Item[] temp = (Item[]) new Object[capacity]; 26 | for (int i = 0; i < n; i++) { 27 | temp[i] = a[i]; 28 | } 29 | a = temp; 30 | 31 | } 32 | 33 | 34 | 35 | public void push(Item item) { 36 | if (n == a.length) resize(2*a.length); 37 | a[n++] = item; 38 | } 39 | 40 | public Item pop() { 41 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 42 | Item item = a[n-1]; 43 | a[n-1] = null; 44 | n--; 45 | if (n > 0 && n == a.length/4) resize(a.length/2); 46 | return item; 47 | } 48 | 49 | 50 | public Item peek() { 51 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 52 | return a[n-1]; 53 | } 54 | 55 | public Iterator iterator() { 56 | return new ReverseArrayIterator(); 57 | } 58 | 59 | private class ReverseArrayIterator implements Iterator { 60 | private int i; 61 | 62 | public ReverseArrayIterator() { 63 | i = n-1; 64 | } 65 | 66 | public boolean hasNext() { 67 | return i >= 0; 68 | } 69 | 70 | public void remove() { 71 | throw new UnsupportedOperationException(); 72 | } 73 | 74 | public Item next() { 75 | if (!hasNext()) throw new NoSuchElementException(); 76 | return a[i--]; 77 | } 78 | } 79 | 80 | 81 | public static void main(String[] args) { 82 | ResizingArrayStack stack = new ResizingArrayStack(); 83 | while (!StdIn.isEmpty()) { 84 | String item = StdIn.readString(); 85 | if (!item.equals("-")) stack.push(item); 86 | else if (!stack.isEmpty()) StdOut.print(stack.pop() + " "); 87 | } 88 | StdOut.println("(" + stack.size() + " left on stack)"); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.8 substring search (Rabin–Karp).java: -------------------------------------------------------------------------------- 1 | import java.math.BigInteger; 2 | import java.util.Random; 3 | 4 | public class RabinKarp { 5 | private String pat; 6 | private long patHash; 7 | private int m; 8 | private long q; 9 | private int R; 10 | private long RM; 11 | 12 | public RabinKarp(char[] pattern, int R) { 13 | this.pat = String.valueOf(pattern); 14 | this.R = R; 15 | throw new UnsupportedOperationException("Operation not supported yet"); 16 | } 17 | 18 | public RabinKarp(String pat) { 19 | this.pat = pat; 20 | R = 256; 21 | m = pat.length(); 22 | q = longRandomPrime(); 23 | 24 | RM = 1; 25 | for (int i = 1; i <= m-1; i++) 26 | RM = (R * RM) % q; 27 | patHash = hash(pat, m); 28 | } 29 | 30 | private long hash(String key, int m) { 31 | long h = 0; 32 | for (int j = 0; j < m; j++) 33 | h = (R * h + key.charAt(j)) % q; 34 | return h; 35 | } 36 | 37 | private boolean check(String txt, int i) { 38 | for (int j = 0; j < m; j++) 39 | if (pat.charAt(j) != txt.charAt(i + j)) 40 | return false; 41 | return true; 42 | } 43 | 44 | 45 | public int search(String txt) { 46 | int n = txt.length(); 47 | if (n < m) return n; 48 | long txtHash = hash(txt, m); 49 | 50 | if ((patHash == txtHash) && check(txt, 0)) 51 | return 0; 52 | 53 | for (int i = m; i < n; i++) { 54 | txtHash = (txtHash + q - RM*txt.charAt(i-m) % q) % q; 55 | txtHash = (txtHash*R + txt.charAt(i)) % q; 56 | 57 | int offset = i - m + 1; 58 | if ((patHash == txtHash) && check(txt, offset)) 59 | return offset; 60 | } 61 | 62 | return n; 63 | } 64 | 65 | 66 | private static long longRandomPrime() { 67 | BigInteger prime = BigInteger.probablePrime(31, new Random()); 68 | return prime.longValue(); 69 | } 70 | 71 | public static void main(String[] args) { 72 | String pat = args[0]; 73 | String txt = args[1]; 74 | 75 | RabinKarp searcher = new RabinKarp(pat); 76 | int offset = searcher.search(txt); 77 | 78 | StdOut.println("text: " + txt); 79 | 80 | StdOut.print("pattern: "); 81 | for (int i = 0; i < offset; i++) 82 | StdOut.print(" "); 83 | StdOut.println(pat); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.6 strong components (Kosaraju–Sharir).java: -------------------------------------------------------------------------------- 1 | public class KosarajuSharirSCC { 2 | private boolean[] marked; 3 | private int[] id; 4 | private int count; 5 | 6 | public KosarajuSharirSCC(Digraph G) { 7 | 8 | DepthFirstOrder dfs = new DepthFirstOrder(G.reverse()); 9 | 10 | marked = new boolean[G.V()]; 11 | id = new int[G.V()]; 12 | for (int v : dfs.reversePost()) { 13 | if (!marked[v]) { 14 | dfs(G, v); 15 | count++; 16 | } 17 | } 18 | 19 | assert check(G); 20 | } 21 | 22 | private void dfs(Digraph G, int v) { 23 | marked[v] = true; 24 | id[v] = count; 25 | for (int w : G.adj(v)) { 26 | if (!marked[w]) dfs(G, w); 27 | } 28 | } 29 | 30 | public int count() { 31 | return count; 32 | } 33 | 34 | public boolean stronglyConnected(int v, int w) { 35 | validateVertex(v); 36 | validateVertex(w); 37 | return id[v] == id[w]; 38 | } 39 | 40 | public int id(int v) { 41 | validateVertex(v); 42 | return id[v]; 43 | } 44 | 45 | private boolean check(Digraph G) { 46 | TransitiveClosure tc = new TransitiveClosure(G); 47 | for (int v = 0; v < G.V(); v++) { 48 | for (int w = 0; w < G.V(); w++) { 49 | if (stronglyConnected(v, w) != (tc.reachable(v, w) && tc.reachable(w, v))) 50 | return false; 51 | } 52 | } 53 | return true; 54 | } 55 | 56 | private void validateVertex(int v) { 57 | int V = marked.length; 58 | if (v < 0 || v >= V) 59 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 60 | } 61 | 62 | public static void main(String[] args) { 63 | In in = new In(args[0]); 64 | Digraph G = new Digraph(in); 65 | KosarajuSharirSCC scc = new KosarajuSharirSCC(G); 66 | 67 | int m = scc.count(); 68 | StdOut.println(m + " strong components"); 69 | 70 | Queue[] components = (Queue[]) new Queue[m]; 71 | for (int i = 0; i < m; i++) { 72 | components[i] = new Queue(); 73 | } 74 | for (int v = 0; v < G.V(); v++) { 75 | components[scc.id(v)].enqueue(v); 76 | } 77 | 78 | for (int i = 0; i < m; i++) { 79 | for (int v : components[i]) { 80 | StdOut.print(v + " "); 81 | } 82 | StdOut.println(); 83 | } 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.10 shortest paths in a DAG.java: -------------------------------------------------------------------------------- 1 | public class AcyclicSP { 2 | private double[] distTo; 3 | private DirectedEdge[] edgeTo; 4 | 5 | 6 | public AcyclicSP(EdgeWeightedDigraph G, int s) { 7 | distTo = new double[G.V()]; 8 | edgeTo = new DirectedEdge[G.V()]; 9 | 10 | validateVertex(s); 11 | 12 | for (int v = 0; v < G.V(); v++) 13 | distTo[v] = Double.POSITIVE_INFINITY; 14 | distTo[s] = 0.0; 15 | 16 | Topological topological = new Topological(G); 17 | if (!topological.hasOrder()) 18 | throw new IllegalArgumentException("Digraph is not acyclic."); 19 | for (int v : topological.order()) { 20 | for (DirectedEdge e : G.adj(v)) 21 | relax(e); 22 | } 23 | } 24 | 25 | private void relax(DirectedEdge e) { 26 | int v = e.from(), w = e.to(); 27 | if (distTo[w] > distTo[v] + e.weight()) { 28 | distTo[w] = distTo[v] + e.weight(); 29 | edgeTo[w] = e; 30 | } 31 | } 32 | 33 | public double distTo(int v) { 34 | validateVertex(v); 35 | return distTo[v]; 36 | } 37 | 38 | public boolean hasPathTo(int v) { 39 | validateVertex(v); 40 | return distTo[v] < Double.POSITIVE_INFINITY; 41 | } 42 | 43 | public Iterable pathTo(int v) { 44 | validateVertex(v); 45 | if (!hasPathTo(v)) return null; 46 | Stack path = new Stack(); 47 | for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) { 48 | path.push(e); 49 | } 50 | return path; 51 | } 52 | 53 | private void validateVertex(int v) { 54 | int V = distTo.length; 55 | if (v < 0 || v >= V) 56 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 57 | } 58 | 59 | public static void main(String[] args) { 60 | In in = new In(args[0]); 61 | int s = Integer.parseInt(args[1]); 62 | EdgeWeightedDigraph G = new EdgeWeightedDigraph(in); 63 | 64 | AcyclicSP sp = new AcyclicSP(G, s); 65 | for (int v = 0; v < G.V(); v++) { 66 | if (sp.hasPathTo(v)) { 67 | StdOut.printf("%d to %d (%.2f) ", s, v, sp.distTo(v)); 68 | for (DirectedEdge e : sp.pathTo(v)) { 69 | StdOut.print(e + " "); 70 | } 71 | StdOut.println(); 72 | } 73 | else { 74 | StdOut.printf("%d to %d no path\n", s, v); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.6 substring search (Knuth–Morris–Pratt).java: -------------------------------------------------------------------------------- 1 | public class KMP { 2 | private final int R; 3 | private int[][] dfa; 4 | 5 | private char[] pattern; 6 | private String pat; 7 | 8 | public KMP(String pat) { 9 | this.R = 256; 10 | this.pat = pat; 11 | 12 | int m = pat.length(); 13 | dfa = new int[R][m]; 14 | dfa[pat.charAt(0)][0] = 1; 15 | for (int x = 0, j = 1; j < m; j++) { 16 | for (int c = 0; c < R; c++) 17 | dfa[c][j] = dfa[c][x]; 18 | dfa[pat.charAt(j)][j] = j+1; 19 | x = dfa[pat.charAt(j)][x]; 20 | } 21 | } 22 | 23 | public KMP(char[] pattern, int R) { 24 | this.R = R; 25 | this.pattern = new char[pattern.length]; 26 | for (int j = 0; j < pattern.length; j++) 27 | this.pattern[j] = pattern[j]; 28 | 29 | int m = pattern.length; 30 | dfa = new int[R][m]; 31 | dfa[pattern[0]][0] = 1; 32 | for (int x = 0, j = 1; j < m; j++) { 33 | for (int c = 0; c < R; c++) 34 | dfa[c][j] = dfa[c][x]; 35 | dfa[pattern[j]][j] = j+1; 36 | x = dfa[pattern[j]][x]; 37 | } 38 | } 39 | 40 | public int search(String txt) { 41 | 42 | int m = pat.length(); 43 | int n = txt.length(); 44 | int i, j; 45 | for (i = 0, j = 0; i < n && j < m; i++) { 46 | j = dfa[txt.charAt(i)][j]; 47 | } 48 | if (j == m) return i - m; 49 | return n; 50 | } 51 | 52 | public int search(char[] text) { 53 | 54 | int m = pattern.length; 55 | int n = text.length; 56 | int i, j; 57 | for (i = 0, j = 0; i < n && j < m; i++) { 58 | j = dfa[text[i]][j]; 59 | } 60 | if (j == m) return i - m; 61 | return n; 62 | } 63 | 64 | 65 | public static void main(String[] args) { 66 | String pat = args[0]; 67 | String txt = args[1]; 68 | char[] pattern = pat.toCharArray(); 69 | char[] text = txt.toCharArray(); 70 | 71 | KMP kmp1 = new KMP(pat); 72 | int offset1 = kmp1.search(txt); 73 | 74 | KMP kmp2 = new KMP(pattern, 256); 75 | int offset2 = kmp2.search(text); 76 | 77 | StdOut.println("text: " + txt); 78 | 79 | StdOut.print("pattern: "); 80 | for (int i = 0; i < offset1; i++) 81 | StdOut.print(" "); 82 | StdOut.println(pat); 83 | 84 | StdOut.print("pattern: "); 85 | for (int i = 0; i < offset2; i++) 86 | StdOut.print(" "); 87 | StdOut.println(pat); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-3.1 sequential search.java: -------------------------------------------------------------------------------- 1 | public class SequentialSearchST { 2 | private int n; 3 | private Node first; 4 | 5 | private class Node { 6 | private Key key; 7 | private Value val; 8 | private Node next; 9 | 10 | public Node(Key key, Value val, Node next) { 11 | this.key = key; 12 | this.val = val; 13 | this.next = next; 14 | } 15 | } 16 | 17 | public SequentialSearchST() { 18 | } 19 | 20 | public int size() { 21 | return n; 22 | } 23 | 24 | public boolean isEmpty() { 25 | return size() == 0; 26 | } 27 | 28 | public boolean contains(Key key) { 29 | if (key == null) throw new IllegalArgumentException("argument to contains() is null"); 30 | return get(key) != null; 31 | } 32 | 33 | public Value get(Key key) { 34 | if (key == null) throw new IllegalArgumentException("argument to get() is null"); 35 | for (Node x = first; x != null; x = x.next) { 36 | if (key.equals(x.key)) 37 | return x.val; 38 | } 39 | return null; 40 | } 41 | 42 | public void put(Key key, Value val) { 43 | if (key == null) throw new IllegalArgumentException("first argument to put() is null"); 44 | if (val == null) { 45 | delete(key); 46 | return; 47 | } 48 | 49 | for (Node x = first; x != null; x = x.next) { 50 | if (key.equals(x.key)) { 51 | x.val = val; 52 | return; 53 | } 54 | } 55 | first = new Node(key, val, first); 56 | n++; 57 | } 58 | public void delete(Key key) { 59 | if (key == null) throw new IllegalArgumentException("argument to delete() is null"); 60 | first = delete(first, key); 61 | } 62 | 63 | private Node delete(Node x, Key key) { 64 | if (x == null) return null; 65 | if (key.equals(x.key)) { 66 | n--; 67 | return x.next; 68 | } 69 | x.next = delete(x.next, key); 70 | return x; 71 | } 72 | 73 | public Iterable keys() { 74 | Queue queue = new Queue(); 75 | for (Node x = first; x != null; x = x.next) 76 | queue.enqueue(x.key); 77 | return queue; 78 | } 79 | 80 | public static void main(String[] args) { 81 | SequentialSearchST st = new SequentialSearchST(); 82 | for (int i = 0; !StdIn.isEmpty(); i++) { 83 | String key = StdIn.readString(); 84 | st.put(key, i); 85 | } 86 | for (String s : st.keys()) 87 | StdOut.println(s + " " + st.get(s)); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Chapter 2 排序 Sorting/2.3 shellsort.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code Shell} class provides static methods for sorting an 3 | * array using Shellsort with Knuth's increment sequence (1, 4, 13, 40, ...). 4 | * @author Robert Sedgewick 5 | * @author Kevin Wayne 6 | */ 7 | public class Shell { 8 | 9 | // This class should not be instantiated. 10 | private Shell() { } 11 | 12 | /** 13 | * Rearranges the array in ascending order, using the natural order. 14 | * @param a the array to be sorted 15 | */ 16 | public static void sort(Comparable[] a) { 17 | int n = a.length; 18 | 19 | // 3x+1 increment sequence: 1, 4, 13, 40, 121, 364, 1093, ... 20 | int h = 1; 21 | while (h < n/3) h = 3*h + 1; 22 | 23 | while (h >= 1) { 24 | // h-sort the array 25 | for (int i = h; i < n; i++) { 26 | for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) { 27 | exch(a, j, j-h); 28 | } 29 | } 30 | assert isHsorted(a, h); 31 | h /= 3; 32 | } 33 | assert isSorted(a); 34 | } 35 | 36 | 37 | 38 | /*************************************************************************** 39 | * Helper sorting functions. 40 | ***************************************************************************/ 41 | 42 | // is v < w ? 43 | private static boolean less(Comparable v, Comparable w) { 44 | return v.compareTo(w) < 0; 45 | } 46 | 47 | // exchange a[i] and a[j] 48 | private static void exch(Object[] a, int i, int j) { 49 | Object swap = a[i]; 50 | a[i] = a[j]; 51 | a[j] = swap; 52 | } 53 | 54 | 55 | /*************************************************************************** 56 | * Check if array is sorted - useful for debugging. 57 | ***************************************************************************/ 58 | private static boolean isSorted(Comparable[] a) { 59 | for (int i = 1; i < a.length; i++) 60 | if (less(a[i], a[i-1])) return false; 61 | return true; 62 | } 63 | 64 | // is the array h-sorted? 65 | private static boolean isHsorted(Comparable[] a, int h) { 66 | for (int i = h; i < a.length; i++) 67 | if (less(a[i], a[i-h])) return false; 68 | return true; 69 | } 70 | 71 | // print array to standard output 72 | private static void show(Comparable[] a) { 73 | for (int i = 0; i < a.length; i++) { 74 | StdOut.println(a[i]); 75 | } 76 | } 77 | 78 | /** 79 | * Reads in a sequence of strings from standard input; Shellsorts them; 80 | * and prints them to standard output in ascending order. 81 | * 82 | * @param args the command-line arguments 83 | */ 84 | public static void main(String[] args) { 85 | String[] a = StdIn.readAllStrings(); 86 | Shell.sort(a); 87 | show(a); 88 | } 89 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.9 NFA for regular expressions.java: -------------------------------------------------------------------------------- 1 | public class NFA { 2 | 3 | private Digraph graph; 4 | private String regexp; 5 | private final int m; 6 | 7 | public NFA(String regexp) { 8 | this.regexp = regexp; 9 | m = regexp.length(); 10 | Stack ops = new Stack(); 11 | graph = new Digraph(m+1); 12 | for (int i = 0; i < m; i++) { 13 | int lp = i; 14 | if (regexp.charAt(i) == '(' || regexp.charAt(i) == '|') 15 | ops.push(i); 16 | else if (regexp.charAt(i) == ')') { 17 | int or = ops.pop(); 18 | 19 | if (regexp.charAt(or) == '|') { 20 | lp = ops.pop(); 21 | graph.addEdge(lp, or+1); 22 | graph.addEdge(or, i); 23 | } 24 | else if (regexp.charAt(or) == '(') 25 | lp = or; 26 | else assert false; 27 | } 28 | 29 | if (i < m-1 && regexp.charAt(i+1) == '*') { 30 | graph.addEdge(lp, i+1); 31 | graph.addEdge(i+1, lp); 32 | } 33 | if (regexp.charAt(i) == '(' || regexp.charAt(i) == '*' || regexp.charAt(i) == ')') 34 | graph.addEdge(i, i+1); 35 | } 36 | if (ops.size() != 0) 37 | throw new IllegalArgumentException("Invalid regular expression"); 38 | } 39 | 40 | public boolean recognizes(String txt) { 41 | DirectedDFS dfs = new DirectedDFS(graph, 0); 42 | Bag pc = new Bag(); 43 | for (int v = 0; v < graph.V(); v++) 44 | if (dfs.marked(v)) pc.add(v); 45 | 46 | for (int i = 0; i < txt.length(); i++) { 47 | if (txt.charAt(i) == '*' || txt.charAt(i) == '|' || txt.charAt(i) == '(' || txt.charAt(i) == ')') 48 | throw new IllegalArgumentException("text contains the metacharacter '" + txt.charAt(i) + "'"); 49 | 50 | Bag match = new Bag(); 51 | for (int v : pc) { 52 | if (v == m) continue; 53 | if ((regexp.charAt(v) == txt.charAt(i)) || regexp.charAt(v) == '.') 54 | match.add(v+1); 55 | } 56 | dfs = new DirectedDFS(graph, match); 57 | pc = new Bag(); 58 | for (int v = 0; v < graph.V(); v++) 59 | if (dfs.marked(v)) pc.add(v); 60 | 61 | if (pc.size() == 0) return false; 62 | } 63 | 64 | for (int v : pc) 65 | if (v == m) return true; 66 | return false; 67 | } 68 | 69 | public static void main(String[] args) { 70 | String regexp = "(" + args[0] + ")"; 71 | String txt = args[1]; 72 | NFA nfa = new NFA(regexp); 73 | StdOut.println(nfa.recognizes(txt)); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-2.5 quicksort.java: -------------------------------------------------------------------------------- 1 | public class Quick { 2 | 3 | private Quick() { } 4 | 5 | public static void sort(Comparable[] a) { 6 | StdRandom.shuffle(a); 7 | sort(a, 0, a.length - 1); 8 | assert isSorted(a); 9 | } 10 | 11 | private static void sort(Comparable[] a, int lo, int hi) { 12 | if (hi <= lo) return; 13 | int j = partition(a, lo, hi); 14 | sort(a, lo, j-1); 15 | sort(a, j+1, hi); 16 | assert isSorted(a, lo, hi); 17 | } 18 | 19 | private static int partition(Comparable[] a, int lo, int hi) { 20 | int i = lo; 21 | int j = hi + 1; 22 | Comparable v = a[lo]; 23 | while (true) { 24 | 25 | while (less(a[++i], v)) 26 | if (i == hi) break; 27 | 28 | while (less(v, a[--j])) 29 | if (j == lo) break; 30 | 31 | if (i >= j) break; 32 | 33 | exch(a, i, j); 34 | } 35 | 36 | exch(a, lo, j); 37 | 38 | return j; 39 | } 40 | 41 | public static Comparable select(Comparable[] a, int k) { 42 | if (k < 0 || k >= a.length) { 43 | throw new IndexOutOfBoundsException("Selected element out of bounds"); 44 | } 45 | StdRandom.shuffle(a); 46 | int lo = 0, hi = a.length - 1; 47 | while (hi > lo) { 48 | int i = partition(a, lo, hi); 49 | if (i > k) hi = i - 1; 50 | else if (i < k) lo = i + 1; 51 | else return a[i]; 52 | } 53 | return a[lo]; 54 | } 55 | 56 | 57 | 58 | 59 | private static boolean less(Comparable v, Comparable w) { 60 | return v.compareTo(w) < 0; 61 | } 62 | 63 | private static void exch(Object[] a, int i, int j) { 64 | Object swap = a[i]; 65 | a[i] = a[j]; 66 | a[j] = swap; 67 | } 68 | 69 | 70 | private static boolean isSorted(Comparable[] a) { 71 | return isSorted(a, 0, a.length - 1); 72 | } 73 | 74 | private static boolean isSorted(Comparable[] a, int lo, int hi) { 75 | for (int i = lo + 1; i <= hi; i++) 76 | if (less(a[i], a[i-1])) return false; 77 | return true; 78 | } 79 | 80 | 81 | private static void show(Comparable[] a) { 82 | for (int i = 0; i < a.length; i++) { 83 | StdOut.println(a[i]); 84 | } 85 | } 86 | 87 | public static void main(String[] args) { 88 | String[] a = StdIn.readAllStrings(); 89 | Quick.sort(a); 90 | show(a); 91 | assert isSorted(a); 92 | 93 | StdRandom.shuffle(a); 94 | 95 | StdOut.println(); 96 | for (int i = 0; i < a.length; i++) { 97 | String ith = (String) Quick.select(a, i); 98 | StdOut.println(ith); 99 | } 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.7 substring search (Boyer–Moore).java: -------------------------------------------------------------------------------- 1 | public class BoyerMoore { 2 | private final int R; 3 | private int[] right; 4 | 5 | private char[] pattern; 6 | private String pat; 7 | 8 | public BoyerMoore(String pat) { 9 | this.R = 256; 10 | this.pat = pat; 11 | 12 | right = new int[R]; 13 | for (int c = 0; c < R; c++) 14 | right[c] = -1; 15 | for (int j = 0; j < pat.length(); j++) 16 | right[pat.charAt(j)] = j; 17 | } 18 | 19 | public BoyerMoore(char[] pattern, int R) { 20 | this.R = R; 21 | this.pattern = new char[pattern.length]; 22 | for (int j = 0; j < pattern.length; j++) 23 | this.pattern[j] = pattern[j]; 24 | 25 | right = new int[R]; 26 | for (int c = 0; c < R; c++) 27 | right[c] = -1; 28 | for (int j = 0; j < pattern.length; j++) 29 | right[pattern[j]] = j; 30 | } 31 | 32 | public int search(String txt) { 33 | int m = pat.length(); 34 | int n = txt.length(); 35 | int skip; 36 | for (int i = 0; i <= n - m; i += skip) { 37 | skip = 0; 38 | for (int j = m-1; j >= 0; j--) { 39 | if (pat.charAt(j) != txt.charAt(i+j)) { 40 | skip = Math.max(1, j - right[txt.charAt(i+j)]); 41 | break; 42 | } 43 | } 44 | if (skip == 0) return i; 45 | } 46 | return n; 47 | } 48 | 49 | 50 | public int search(char[] text) { 51 | int m = pattern.length; 52 | int n = text.length; 53 | int skip; 54 | for (int i = 0; i <= n - m; i += skip) { 55 | skip = 0; 56 | for (int j = m-1; j >= 0; j--) { 57 | if (pattern[j] != text[i+j]) { 58 | skip = Math.max(1, j - right[text[i+j]]); 59 | break; 60 | } 61 | } 62 | if (skip == 0) return i; 63 | } 64 | return n; 65 | } 66 | 67 | 68 | public static void main(String[] args) { 69 | String pat = args[0]; 70 | String txt = args[1]; 71 | char[] pattern = pat.toCharArray(); 72 | char[] text = txt.toCharArray(); 73 | 74 | BoyerMoore boyermoore1 = new BoyerMoore(pat); 75 | BoyerMoore boyermoore2 = new BoyerMoore(pattern, 256); 76 | int offset1 = boyermoore1.search(txt); 77 | int offset2 = boyermoore2.search(text); 78 | 79 | StdOut.println("text: " + txt); 80 | 81 | StdOut.print("pattern: "); 82 | for (int i = 0; i < offset1; i++) 83 | StdOut.print(" "); 84 | StdOut.println(pat); 85 | 86 | StdOut.print("pattern: "); 87 | for (int i = 0; i < offset2; i++) 88 | StdOut.print(" "); 89 | StdOut.println(pat); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /chapter 1 基础 Fundamental/1.4 multiset (linked list).java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.NoSuchElementException; 3 | 4 | /** 5 | * The {@code LinkedBag} class represents a bag (or multiset) of 6 | * generic items. It supports insertion and iterating over the 7 | * items in arbitrary order. 8 | * This implementation uses a singly-linked list with a non-static nested class Node. 9 | * See {@link Bag} for a version that uses a static nested class. 10 | * The add, isEmpty, and size operations 11 | * take constant time. Iteration takes time proportional to the number of items. 12 | * @author Robert Sedgewick 13 | * @author Kevin Wayne 14 | */ 15 | public class LinkedBag implements Iterable { 16 | private Node first; // beginning of bag 17 | private int n; // number of elements in bag 18 | 19 | // helper linked list class 20 | private class Node { 21 | private Item item; 22 | private Node next; 23 | } 24 | 25 | /** 26 | * Initializes an empty bag. 27 | */ 28 | public LinkedBag() { 29 | first = null; 30 | n = 0; 31 | } 32 | 33 | /** 34 | * Is this bag empty? 35 | * @return true if this bag is empty; false otherwise 36 | */ 37 | public boolean isEmpty() { 38 | return first == null; 39 | } 40 | 41 | /** 42 | * Returns the number of items in this bag. 43 | * @return the number of items in this bag 44 | */ 45 | public int size() { 46 | return n; 47 | } 48 | 49 | /** 50 | * Adds the item to this bag. 51 | * @param item the item to add to this bag 52 | */ 53 | public void add(Item item) { 54 | Node oldfirst = first; 55 | first = new Node(); 56 | first.item = item; 57 | first.next = oldfirst; 58 | n++; 59 | } 60 | 61 | 62 | /** 63 | * Returns an iterator that iterates over the items in the bag. 64 | */ 65 | public Iterator iterator() { 66 | return new ListIterator(); 67 | } 68 | 69 | // an iterator, doesn't implement remove() since it's optional 70 | private class ListIterator implements Iterator { 71 | private Node current = first; 72 | 73 | public boolean hasNext() { return current != null; } 74 | public void remove() { throw new UnsupportedOperationException(); } 75 | 76 | public Item next() { 77 | if (!hasNext()) throw new NoSuchElementException(); 78 | Item item = current.item; 79 | current = current.next; 80 | return item; 81 | } 82 | } 83 | 84 | /** 85 | * Unit tests the {@code LinkedBag} data type. 86 | * 87 | * @param args the command-line arguments 88 | */ 89 | public static void main(String[] args) { 90 | LinkedBag bag = new LinkedBag(); 91 | while (!StdIn.isEmpty()) { 92 | String item = StdIn.readString(); 93 | bag.add(item); 94 | } 95 | 96 | StdOut.println("size of bag = " + bag.size()); 97 | for (String s : bag) { 98 | StdOut.println(s); 99 | } 100 | } 101 | 102 | 103 | } -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.8 MST (Kruskal).java: -------------------------------------------------------------------------------- 1 | public class KruskalMST { 2 | private static final double FLOATING_POINT_EPSILON = 1E-12; 3 | 4 | private double weight; 5 | private Queue mst = new Queue(); 6 | 7 | public KruskalMST(EdgeWeightedGraph G) { 8 | MinPQ pq = new MinPQ(); 9 | for (Edge e : G.edges()) { 10 | pq.insert(e); 11 | } 12 | 13 | UF uf = new UF(G.V()); 14 | while (!pq.isEmpty() && mst.size() < G.V() - 1) { 15 | Edge e = pq.delMin(); 16 | int v = e.either(); 17 | int w = e.other(v); 18 | if (!uf.connected(v, w)) { 19 | uf.union(v, w); 20 | mst.enqueue(e); 21 | weight += e.weight(); 22 | } 23 | } 24 | 25 | assert check(G); 26 | } 27 | 28 | public Iterable edges() { 29 | return mst; 30 | } 31 | 32 | public double weight() { 33 | return weight; 34 | } 35 | 36 | private boolean check(EdgeWeightedGraph G) { 37 | 38 | double total = 0.0; 39 | for (Edge e : edges()) { 40 | total += e.weight(); 41 | } 42 | if (Math.abs(total - weight()) > FLOATING_POINT_EPSILON) { 43 | System.err.printf("Weight of edges does not equal weight(): %f vs. %f\n", total, weight()); 44 | return false; 45 | } 46 | 47 | UF uf = new UF(G.V()); 48 | for (Edge e : edges()) { 49 | int v = e.either(), w = e.other(v); 50 | if (uf.connected(v, w)) { 51 | System.err.println("Not a forest"); 52 | return false; 53 | } 54 | uf.union(v, w); 55 | } 56 | 57 | for (Edge e : G.edges()) { 58 | int v = e.either(), w = e.other(v); 59 | if (!uf.connected(v, w)) { 60 | System.err.println("Not a spanning forest"); 61 | return false; 62 | } 63 | } 64 | 65 | for (Edge e : edges()) { 66 | 67 | uf = new UF(G.V()); 68 | for (Edge f : mst) { 69 | int x = f.either(), y = f.other(x); 70 | if (f != e) uf.union(x, y); 71 | } 72 | 73 | for (Edge f : G.edges()) { 74 | int x = f.either(), y = f.other(x); 75 | if (!uf.connected(x, y)) { 76 | if (f.weight() < e.weight()) { 77 | System.err.println("Edge " + f + " violates cut optimality conditions"); 78 | return false; 79 | } 80 | } 81 | } 82 | 83 | } 84 | 85 | return true; 86 | } 87 | 88 | 89 | public static void main(String[] args) { 90 | In in = new In(args[0]); 91 | EdgeWeightedGraph G = new EdgeWeightedGraph(in); 92 | KruskalMST mst = new KruskalMST(G); 93 | for (Edge e : mst.edges()) { 94 | StdOut.println(e); 95 | } 96 | StdOut.printf("%.5f\n", mst.weight()); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.3 connected components of a graph.java: -------------------------------------------------------------------------------- 1 | public class CC { 2 | private boolean[] marked; 3 | private int[] id; 4 | private int[] size; 5 | private int count; 6 | 7 | public CC(Graph G) { 8 | marked = new boolean[G.V()]; 9 | id = new int[G.V()]; 10 | size = new int[G.V()]; 11 | for (int v = 0; v < G.V(); v++) { 12 | if (!marked[v]) { 13 | dfs(G, v); 14 | count++; 15 | } 16 | } 17 | } 18 | 19 | public CC(EdgeWeightedGraph G) { 20 | marked = new boolean[G.V()]; 21 | id = new int[G.V()]; 22 | size = new int[G.V()]; 23 | for (int v = 0; v < G.V(); v++) { 24 | if (!marked[v]) { 25 | dfs(G, v); 26 | count++; 27 | } 28 | } 29 | } 30 | 31 | private void dfs(Graph G, int v) { 32 | marked[v] = true; 33 | id[v] = count; 34 | size[count]++; 35 | for (int w : G.adj(v)) { 36 | if (!marked[w]) { 37 | dfs(G, w); 38 | } 39 | } 40 | } 41 | 42 | private void dfs(EdgeWeightedGraph G, int v) { 43 | marked[v] = true; 44 | id[v] = count; 45 | size[count]++; 46 | for (Edge e : G.adj(v)) { 47 | int w = e.other(v); 48 | if (!marked[w]) { 49 | dfs(G, w); 50 | } 51 | } 52 | } 53 | 54 | 55 | public int id(int v) { 56 | validateVertex(v); 57 | return id[v]; 58 | } 59 | 60 | public int size(int v) { 61 | validateVertex(v); 62 | return size[id[v]]; 63 | } 64 | 65 | public int count() { 66 | return count; 67 | } 68 | 69 | public boolean connected(int v, int w) { 70 | validateVertex(v); 71 | validateVertex(w); 72 | return id(v) == id(w); 73 | } 74 | 75 | @Deprecated 76 | public boolean areConnected(int v, int w) { 77 | validateVertex(v); 78 | validateVertex(w); 79 | return id(v) == id(w); 80 | } 81 | 82 | private void validateVertex(int v) { 83 | int V = marked.length; 84 | if (v < 0 || v >= V) 85 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 86 | } 87 | 88 | public static void main(String[] args) { 89 | In in = new In(args[0]); 90 | Graph G = new Graph(in); 91 | CC cc = new CC(G); 92 | 93 | int m = cc.count(); 94 | StdOut.println(m + " components"); 95 | 96 | Queue[] components = (Queue[]) new Queue[m]; 97 | for (int i = 0; i < m; i++) { 98 | components[i] = new Queue(); 99 | } 100 | for (int v = 0; v < G.V(); v++) { 101 | components[cc.id(v)].enqueue(v); 102 | } 103 | 104 | for (int i = 0; i < m; i++) { 105 | for (int v : components[i]) { 106 | StdOut.print(v + " "); 107 | } 108 | StdOut.println(); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Chapter 5 字符串 Strings/5.11 data compression (Lempel–Ziv–Welch).java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code LZW} class provides static methods for compressing 3 | * and expanding a binary input using LZW compression over the 8-bit extended 4 | * ASCII alphabet with 12-bit codewords. 5 | * @author Robert Sedgewick 6 | * @author Kevin Wayne 7 | */ 8 | public class LZW { 9 | private static final int R = 256; // number of input chars 10 | private static final int L = 4096; // number of codewords = 2^W 11 | private static final int W = 12; // codeword width 12 | 13 | // Do not instantiate. 14 | private LZW() { } 15 | 16 | /** 17 | * Reads a sequence of 8-bit bytes from standard input; compresses 18 | * them using LZW compression with 12-bit codewords; and writes the results 19 | * to standard output. 20 | */ 21 | public static void compress() { 22 | String input = BinaryStdIn.readString(); 23 | TST st = new TST(); 24 | for (int i = 0; i < R; i++) 25 | st.put("" + (char) i, i); 26 | int code = R+1; // R is codeword for EOF 27 | 28 | while (input.length() > 0) { 29 | String s = st.longestPrefixOf(input); // Find max prefix match s. 30 | BinaryStdOut.write(st.get(s), W); // Print s's encoding. 31 | int t = s.length(); 32 | if (t < input.length() && code < L) // Add s to symbol table. 33 | st.put(input.substring(0, t + 1), code++); 34 | input = input.substring(t); // Scan past s in input. 35 | } 36 | BinaryStdOut.write(R, W); 37 | BinaryStdOut.close(); 38 | } 39 | 40 | /** 41 | * Reads a sequence of bit encoded using LZW compression with 42 | * 12-bit codewords from standard input; expands them; and writes 43 | * the results to standard output. 44 | */ 45 | public static void expand() { 46 | String[] st = new String[L]; 47 | int i; // next available codeword value 48 | 49 | // initialize symbol table with all 1-character strings 50 | for (i = 0; i < R; i++) 51 | st[i] = "" + (char) i; 52 | st[i++] = ""; // (unused) lookahead for EOF 53 | 54 | int codeword = BinaryStdIn.readInt(W); 55 | if (codeword == R) return; // expanded message is empty string 56 | String val = st[codeword]; 57 | 58 | while (true) { 59 | BinaryStdOut.write(val); 60 | codeword = BinaryStdIn.readInt(W); 61 | if (codeword == R) break; 62 | String s = st[codeword]; 63 | if (i == codeword) s = val + val.charAt(0); // special case hack 64 | if (i < L) st[i++] = val + s.charAt(0); 65 | val = s; 66 | } 67 | BinaryStdOut.close(); 68 | } 69 | 70 | /** 71 | * Sample client that calls {@code compress()} if the command-line 72 | * argument is "-" an {@code expand()} if it is "+". 73 | * 74 | * @param args the command-line arguments 75 | */ 76 | public static void main(String[] args) { 77 | if (args[0].equals("-")) compress(); 78 | else if (args[0].equals("+")) expand(); 79 | else throw new IllegalArgumentException("Illegal command line argument"); 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-3.5 separate chaining hash table.java: -------------------------------------------------------------------------------- 1 | public class SeparateChainingHashST { 2 | private static final int INIT_CAPACITY = 4; 3 | 4 | private int n; 5 | private int m; 6 | private SequentialSearchST[] st; 7 | 8 | 9 | public SeparateChainingHashST() { 10 | this(INIT_CAPACITY); 11 | } 12 | 13 | public SeparateChainingHashST(int m) { 14 | this.m = m; 15 | st = (SequentialSearchST[]) new SequentialSearchST[m]; 16 | for (int i = 0; i < m; i++) 17 | st[i] = new SequentialSearchST(); 18 | } 19 | 20 | private void resize(int chains) { 21 | SeparateChainingHashST temp = new SeparateChainingHashST(chains); 22 | for (int i = 0; i < m; i++) { 23 | for (Key key : st[i].keys()) { 24 | temp.put(key, st[i].get(key)); 25 | } 26 | } 27 | this.m = temp.m; 28 | this.n = temp.n; 29 | this.st = temp.st; 30 | } 31 | 32 | private int hash(Key key) { 33 | return (key.hashCode() & 0x7fffffff) % m; 34 | } 35 | 36 | public int size() { 37 | return n; 38 | } 39 | 40 | public boolean isEmpty() { 41 | return size() == 0; 42 | } 43 | 44 | public boolean contains(Key key) { 45 | if (key == null) throw new IllegalArgumentException("argument to contains() is null"); 46 | return get(key) != null; 47 | } 48 | 49 | public Value get(Key key) { 50 | if (key == null) throw new IllegalArgumentException("argument to get() is null"); 51 | int i = hash(key); 52 | return st[i].get(key); 53 | } 54 | 55 | public void put(Key key, Value val) { 56 | if (key == null) throw new IllegalArgumentException("first argument to put() is null"); 57 | if (val == null) { 58 | delete(key); 59 | return; 60 | } 61 | 62 | if (n >= 10*m) resize(2*m); 63 | 64 | int i = hash(key); 65 | if (!st[i].contains(key)) n++; 66 | st[i].put(key, val); 67 | } 68 | 69 | public void delete(Key key) { 70 | if (key == null) throw new IllegalArgumentException("argument to delete() is null"); 71 | 72 | int i = hash(key); 73 | if (st[i].contains(key)) n--; 74 | st[i].delete(key); 75 | 76 | if (m > INIT_CAPACITY && n <= 2*m) resize(m/2); 77 | } 78 | 79 | public Iterable keys() { 80 | Queue queue = new Queue(); 81 | for (int i = 0; i < m; i++) { 82 | for (Key key : st[i].keys()) 83 | queue.enqueue(key); 84 | } 85 | return queue; 86 | } 87 | 88 | 89 | public static void main(String[] args) { 90 | SeparateChainingHashST st = new SeparateChainingHashST(); 91 | for (int i = 0; !StdIn.isEmpty(); i++) { 92 | String key = StdIn.readString(); 93 | st.put(key, i); 94 | } 95 | 96 | for (String s : st.keys()) 97 | StdOut.println(s + " " + st.get(s)); 98 | 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-2.4 top-down mergesort.java: -------------------------------------------------------------------------------- 1 | public class Merge { 2 | 3 | private Merge() { } 4 | 5 | private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) { 6 | assert isSorted(a, lo, mid); 7 | assert isSorted(a, mid+1, hi); 8 | 9 | for (int k = lo; k <= hi; k++) { 10 | aux[k] = a[k]; 11 | } 12 | 13 | int i = lo, j = mid+1; 14 | for (int k = lo; k <= hi; k++) { 15 | if (i > mid) a[k] = aux[j++]; 16 | else if (j > hi) a[k] = aux[i++]; 17 | else if (less(aux[j], aux[i])) a[k] = aux[j++]; 18 | else a[k] = aux[i++]; 19 | } 20 | 21 | assert isSorted(a, lo, hi); 22 | } 23 | 24 | private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) { 25 | if (hi <= lo) return; 26 | int mid = lo + (hi - lo) / 2; 27 | sort(a, aux, lo, mid); 28 | sort(a, aux, mid + 1, hi); 29 | merge(a, aux, lo, mid, hi); 30 | } 31 | 32 | public static void sort(Comparable[] a) { 33 | Comparable[] aux = new Comparable[a.length]; 34 | sort(a, aux, 0, a.length-1); 35 | assert isSorted(a); 36 | } 37 | 38 | 39 | 40 | private static boolean less(Comparable v, Comparable w) { 41 | return v.compareTo(w) < 0; 42 | } 43 | 44 | private static boolean isSorted(Comparable[] a) { 45 | return isSorted(a, 0, a.length - 1); 46 | } 47 | 48 | private static boolean isSorted(Comparable[] a, int lo, int hi) { 49 | for (int i = lo + 1; i <= hi; i++) 50 | if (less(a[i], a[i-1])) return false; 51 | return true; 52 | } 53 | 54 | 55 | private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) { 56 | 57 | for (int k = lo; k <= hi; k++) { 58 | aux[k] = index[k]; 59 | } 60 | 61 | int i = lo, j = mid+1; 62 | for (int k = lo; k <= hi; k++) { 63 | if (i > mid) index[k] = aux[j++]; 64 | else if (j > hi) index[k] = aux[i++]; 65 | else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++]; 66 | else index[k] = aux[i++]; 67 | } 68 | } 69 | 70 | public static int[] indexSort(Comparable[] a) { 71 | int n = a.length; 72 | int[] index = new int[n]; 73 | for (int i = 0; i < n; i++) 74 | index[i] = i; 75 | 76 | int[] aux = new int[n]; 77 | sort(a, index, aux, 0, n-1); 78 | return index; 79 | } 80 | 81 | private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) { 82 | if (hi <= lo) return; 83 | int mid = lo + (hi - lo) / 2; 84 | sort(a, index, aux, lo, mid); 85 | sort(a, index, aux, mid + 1, hi); 86 | merge(a, index, aux, lo, mid, hi); 87 | } 88 | 89 | private static void show(Comparable[] a) { 90 | for (int i = 0; i < a.length; i++) { 91 | StdOut.println(a[i]); 92 | } 93 | } 94 | 95 | public static void main(String[] args) { 96 | String[] a = StdIn.readAllStrings(); 97 | Merge.sort(a); 98 | show(a); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-1.2 LIFO stack (linked list).java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.NoSuchElementException; 3 | 4 | 5 | public class LinkedStack implements Iterable { 6 | private int n; 7 | private Node first; 8 | 9 | private class Node { 10 | private Item item; 11 | private Node next; 12 | } 13 | 14 | public LinkedStack() { 15 | first = null; 16 | n = 0; 17 | assert check(); 18 | } 19 | 20 | public boolean isEmpty() { 21 | return first == null; 22 | } 23 | 24 | public int size() { 25 | return n; 26 | } 27 | 28 | public void push(Item item) { 29 | Node oldfirst = first; 30 | first = new Node(); 31 | first.item = item; 32 | first.next = oldfirst; 33 | n++; 34 | assert check(); 35 | } 36 | 37 | public Item pop() { 38 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 39 | Item item = first.item; 40 | first = first.next; 41 | n--; 42 | assert check(); 43 | return item; 44 | } 45 | 46 | 47 | public Item peek() { 48 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 49 | return first.item; 50 | } 51 | 52 | public String toString() { 53 | StringBuilder s = new StringBuilder(); 54 | for (Item item : this) 55 | s.append(item + " "); 56 | return s.toString(); 57 | } 58 | 59 | public Iterator iterator() { 60 | return new ListIterator(); 61 | } 62 | 63 | private class ListIterator implements Iterator { 64 | private Node current = first; 65 | public boolean hasNext() { return current != null; } 66 | public void remove() { throw new UnsupportedOperationException(); } 67 | 68 | public Item next() { 69 | if (!hasNext()) throw new NoSuchElementException(); 70 | Item item = current.item; 71 | current = current.next; 72 | return item; 73 | } 74 | } 75 | 76 | 77 | private boolean check() { 78 | 79 | if (n < 0) { 80 | return false; 81 | } 82 | if (n == 0) { 83 | if (first != null) return false; 84 | } 85 | else if (n == 1) { 86 | if (first == null) return false; 87 | if (first.next != null) return false; 88 | } 89 | else { 90 | if (first == null) return false; 91 | if (first.next == null) return false; 92 | } 93 | 94 | int numberOfNodes = 0; 95 | for (Node x = first; x != null && numberOfNodes <= n; x = x.next) { 96 | numberOfNodes++; 97 | } 98 | if (numberOfNodes != n) return false; 99 | 100 | return true; 101 | } 102 | 103 | public static void main(String[] args) { 104 | LinkedStack stack = new LinkedStack(); 105 | while (!StdIn.isEmpty()) { 106 | String item = StdIn.readString(); 107 | if (!item.equals("-")) 108 | stack.push(item); 109 | else if (!stack.isEmpty()) 110 | StdOut.print(stack.pop() + " "); 111 | } 112 | StdOut.println("(" + stack.size() + " left on stack)"); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-2.1 insertion sort.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | public class Insertion { 4 | 5 | private Insertion() { } 6 | 7 | public static void sort(Comparable[] a) { 8 | int n = a.length; 9 | for (int i = 0; i < n; i++) { 10 | for (int j = i; j > 0 && less(a[j], a[j-1]); j--) { 11 | exch(a, j, j-1); 12 | } 13 | assert isSorted(a, 0, i); 14 | } 15 | assert isSorted(a); 16 | } 17 | 18 | public static void sort(Comparable[] a, int lo, int hi) { 19 | for (int i = lo; i < hi; i++) { 20 | for (int j = i; j > lo && less(a[j], a[j-1]); j--) { 21 | exch(a, j, j-1); 22 | } 23 | } 24 | assert isSorted(a, lo, hi); 25 | } 26 | 27 | public static void sort(Object[] a, Comparator comparator) { 28 | int n = a.length; 29 | for (int i = 0; i < n; i++) { 30 | for (int j = i; j > 0 && less(a[j], a[j-1], comparator); j--) { 31 | exch(a, j, j-1); 32 | } 33 | assert isSorted(a, 0, i, comparator); 34 | } 35 | assert isSorted(a, comparator); 36 | } 37 | 38 | public static void sort(Object[] a, int lo, int hi, Comparator comparator) { 39 | for (int i = lo; i < hi; i++) { 40 | for (int j = i; j > lo && less(a[j], a[j-1], comparator); j--) { 41 | exch(a, j, j-1); 42 | } 43 | } 44 | assert isSorted(a, lo, hi, comparator); 45 | } 46 | 47 | 48 | public static int[] indexSort(Comparable[] a) { 49 | int n = a.length; 50 | int[] index = new int[n]; 51 | for (int i = 0; i < n; i++) 52 | index[i] = i; 53 | 54 | for (int i = 0; i < n; i++) 55 | for (int j = i; j > 0 && less(a[index[j]], a[index[j-1]]); j--) 56 | exch(index, j, j-1); 57 | 58 | return index; 59 | } 60 | 61 | 62 | private static boolean less(Comparable v, Comparable w) { 63 | return v.compareTo(w) < 0; 64 | } 65 | 66 | private static boolean less(Object v, Object w, Comparator comparator) { 67 | return comparator.compare(v, w) < 0; 68 | } 69 | 70 | private static void exch(Object[] a, int i, int j) { 71 | Object swap = a[i]; 72 | a[i] = a[j]; 73 | a[j] = swap; 74 | } 75 | 76 | private static void exch(int[] a, int i, int j) { 77 | int swap = a[i]; 78 | a[i] = a[j]; 79 | a[j] = swap; 80 | } 81 | 82 | private static boolean isSorted(Comparable[] a) { 83 | return isSorted(a, 0, a.length); 84 | } 85 | 86 | private static boolean isSorted(Comparable[] a, int lo, int hi) { 87 | for (int i = lo+1; i < hi; i++) 88 | if (less(a[i], a[i-1])) return false; 89 | return true; 90 | } 91 | 92 | private static boolean isSorted(Object[] a, Comparator comparator) { 93 | return isSorted(a, 0, a.length, comparator); 94 | } 95 | 96 | private static boolean isSorted(Object[] a, int lo, int hi, Comparator comparator) { 97 | for (int i = lo+1; i < hi; i++) 98 | if (less(a[i], a[i-1], comparator)) return false; 99 | return true; 100 | } 101 | 102 | private static void show(Comparable[] a) { 103 | for (int i = 0; i < a.length; i++) { 104 | StdOut.println(a[i]); 105 | } 106 | } 107 | 108 | public static void main(String[] args) { 109 | String[] a = StdIn.readAllStrings(); 110 | Insertion.sort(a); 111 | show(a); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Chapter 4 图 Graph/4.1 paths in a graph (DFS).java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code DepthFirstPaths} class represents a data type for finding 3 | * paths from a source vertex s to every other vertex 4 | * in an undirected graph. 5 | * This implementation uses depth-first search. 6 | * The constructor takes time proportional to V + E, 7 | * where V is the number of vertices and E is the number of edges. 8 | * It uses extra space (not including the graph) proportional to V. 9 | * @author Robert Sedgewick 10 | * @author Kevin Wayne 11 | */ 12 | public class DepthFirstPaths { 13 | private boolean[] marked; // marked[v] = is there an s-v path? 14 | private int[] edgeTo; // edgeTo[v] = last edge on s-v path 15 | private final int s; // source vertex 16 | 17 | /** 18 | * Computes a path between {@code s} and every other vertex in graph {@code G}. 19 | * @param G the graph 20 | * @param s the source vertex 21 | * @throws IllegalArgumentException unless {@code 0 <= s < V} 22 | */ 23 | public DepthFirstPaths(Graph G, int s) { 24 | this.s = s; 25 | edgeTo = new int[G.V()]; 26 | marked = new boolean[G.V()]; 27 | validateVertex(s); 28 | dfs(G, s); 29 | } 30 | 31 | // depth first search from v 32 | private void dfs(Graph G, int v) { 33 | marked[v] = true; 34 | for (int w : G.adj(v)) { 35 | if (!marked[w]) { 36 | edgeTo[w] = v; 37 | dfs(G, w); 38 | } 39 | } 40 | } 41 | 42 | /** 43 | * Is there a path between the source vertex {@code s} and vertex {@code v}? 44 | * @param v the vertex 45 | * @return {@code true} if there is a path, {@code false} otherwise 46 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 47 | */ 48 | public boolean hasPathTo(int v) { 49 | validateVertex(v); 50 | return marked[v]; 51 | } 52 | 53 | /** 54 | * Returns a path between the source vertex {@code s} and vertex {@code v}, or 55 | * {@code null} if no such path. 56 | * @param v the vertex 57 | * @return the sequence of vertices on a path between the source vertex 58 | * {@code s} and vertex {@code v}, as an Iterable 59 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 60 | */ 61 | public Iterable pathTo(int v) { 62 | validateVertex(v); 63 | if (!hasPathTo(v)) return null; 64 | Stack path = new Stack(); 65 | for (int x = v; x != s; x = edgeTo[x]) 66 | path.push(x); 67 | path.push(s); 68 | return path; 69 | } 70 | 71 | // throw an IllegalArgumentException unless {@code 0 <= v < V} 72 | private void validateVertex(int v) { 73 | int V = marked.length; 74 | if (v < 0 || v >= V) 75 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 76 | } 77 | 78 | /** 79 | * Unit tests the {@code DepthFirstPaths} data type. 80 | * 81 | * @param args the command-line arguments 82 | */ 83 | public static void main(String[] args) { 84 | In in = new In(args[0]); 85 | Graph G = new Graph(in); 86 | int s = Integer.parseInt(args[1]); 87 | DepthFirstPaths dfs = new DepthFirstPaths(G, s); 88 | 89 | for (int v = 0; v < G.V(); v++) { 90 | if (dfs.hasPathTo(v)) { 91 | StdOut.printf("%d to %d: ", s, v); 92 | for (int x : dfs.pathTo(v)) { 93 | if (x == s) StdOut.print(x); 94 | else StdOut.print("-" + x); 95 | } 96 | StdOut.println(); 97 | } 98 | 99 | else { 100 | StdOut.printf("%d to %d: not connected\n", s, v); 101 | } 102 | 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /Chapter 5 字符串 Strings/5.3 three-way string quicksort.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code Quick3string} class provides static methods for sorting an 3 | * array of strings using 3-way radix quicksort. 4 | * @author Robert Sedgewick 5 | * @author Kevin Wayne 6 | */ 7 | public class Quick3string { 8 | private static final int CUTOFF = 15; // cutoff to insertion sort 9 | 10 | // do not instantiate 11 | private Quick3string() { } 12 | 13 | /** 14 | * Rearranges the array of strings in ascending order. 15 | * 16 | * @param a the array to be sorted 17 | */ 18 | public static void sort(String[] a) { 19 | StdRandom.shuffle(a); 20 | sort(a, 0, a.length-1, 0); 21 | assert isSorted(a); 22 | } 23 | 24 | // return the dth character of s, -1 if d = length of s 25 | private static int charAt(String s, int d) { 26 | assert d >= 0 && d <= s.length(); 27 | if (d == s.length()) return -1; 28 | return s.charAt(d); 29 | } 30 | 31 | 32 | // 3-way string quicksort a[lo..hi] starting at dth character 33 | private static void sort(String[] a, int lo, int hi, int d) { 34 | 35 | // cutoff to insertion sort for small subarrays 36 | if (hi <= lo + CUTOFF) { 37 | insertion(a, lo, hi, d); 38 | return; 39 | } 40 | 41 | int lt = lo, gt = hi; 42 | int v = charAt(a[lo], d); 43 | int i = lo + 1; 44 | while (i <= gt) { 45 | int t = charAt(a[i], d); 46 | if (t < v) exch(a, lt++, i++); 47 | else if (t > v) exch(a, i, gt--); 48 | else i++; 49 | } 50 | 51 | // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi]. 52 | sort(a, lo, lt-1, d); 53 | if (v >= 0) sort(a, lt, gt, d+1); 54 | sort(a, gt+1, hi, d); 55 | } 56 | 57 | // sort from a[lo] to a[hi], starting at the dth character 58 | private static void insertion(String[] a, int lo, int hi, int d) { 59 | for (int i = lo; i <= hi; i++) 60 | for (int j = i; j > lo && less(a[j], a[j-1], d); j--) 61 | exch(a, j, j-1); 62 | } 63 | 64 | // exchange a[i] and a[j] 65 | private static void exch(String[] a, int i, int j) { 66 | String temp = a[i]; 67 | a[i] = a[j]; 68 | a[j] = temp; 69 | } 70 | 71 | // is v less than w, starting at character d 72 | // DEPRECATED BECAUSE OF SLOW SUBSTRING EXTRACTION IN JAVA 7 73 | // private static boolean less(String v, String w, int d) { 74 | // assert v.substring(0, d).equals(w.substring(0, d)); 75 | // return v.substring(d).compareTo(w.substring(d)) < 0; 76 | // } 77 | 78 | // is v less than w, starting at character d 79 | private static boolean less(String v, String w, int d) { 80 | assert v.substring(0, d).equals(w.substring(0, d)); 81 | for (int i = d; i < Math.min(v.length(), w.length()); i++) { 82 | if (v.charAt(i) < w.charAt(i)) return true; 83 | if (v.charAt(i) > w.charAt(i)) return false; 84 | } 85 | return v.length() < w.length(); 86 | } 87 | 88 | // is the array sorted 89 | private static boolean isSorted(String[] a) { 90 | for (int i = 1; i < a.length; i++) 91 | if (a[i].compareTo(a[i-1]) < 0) return false; 92 | return true; 93 | } 94 | 95 | 96 | /** 97 | * Reads in a sequence of fixed-length strings from standard input; 98 | * 3-way radix quicksorts them; 99 | * and prints them to standard output in ascending order. 100 | * 101 | * @param args the command-line arguments 102 | */ 103 | public static void main(String[] args) { 104 | 105 | // read in the strings from standard input 106 | String[] a = StdIn.readAllStrings(); 107 | int n = a.length; 108 | 109 | // sort the strings 110 | sort(a); 111 | 112 | // print the results 113 | for (int i = 0; i < n; i++) 114 | StdOut.println(a[i]); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Chapter 2 排序 Sorting/2.2 selection sort.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | /** 4 | * The {@code Selection} class provides static methods for sorting an 5 | * array using selection sort. 6 | * @author Robert Sedgewick 7 | * @author Kevin Wayne 8 | */ 9 | public class Selection { 10 | 11 | // This class should not be instantiated. 12 | private Selection() { } 13 | 14 | /** 15 | * Rearranges the array in ascending order, using the natural order. 16 | * @param a the array to be sorted 17 | */ 18 | public static void sort(Comparable[] a) { 19 | int n = a.length; 20 | for (int i = 0; i < n; i++) { 21 | int min = i; 22 | for (int j = i+1; j < n; j++) { 23 | if (less(a[j], a[min])) min = j; 24 | } 25 | exch(a, i, min); 26 | assert isSorted(a, 0, i); 27 | } 28 | assert isSorted(a); 29 | } 30 | 31 | /** 32 | * Rearranges the array in ascending order, using a comparator. 33 | * @param a the array 34 | * @param comparator the comparator specifying the order 35 | */ 36 | public static void sort(Object[] a, Comparator comparator) { 37 | int n = a.length; 38 | for (int i = 0; i < n; i++) { 39 | int min = i; 40 | for (int j = i+1; j < n; j++) { 41 | if (less(comparator, a[j], a[min])) min = j; 42 | } 43 | exch(a, i, min); 44 | assert isSorted(a, comparator, 0, i); 45 | } 46 | assert isSorted(a, comparator); 47 | } 48 | 49 | 50 | /*************************************************************************** 51 | * Helper sorting functions. 52 | ***************************************************************************/ 53 | 54 | // is v < w ? 55 | private static boolean less(Comparable v, Comparable w) { 56 | return v.compareTo(w) < 0; 57 | } 58 | 59 | // is v < w ? 60 | private static boolean less(Comparator comparator, Object v, Object w) { 61 | return comparator.compare(v, w) < 0; 62 | } 63 | 64 | 65 | // exchange a[i] and a[j] 66 | private static void exch(Object[] a, int i, int j) { 67 | Object swap = a[i]; 68 | a[i] = a[j]; 69 | a[j] = swap; 70 | } 71 | 72 | 73 | /*************************************************************************** 74 | * Check if array is sorted - useful for debugging. 75 | ***************************************************************************/ 76 | 77 | // is the array a[] sorted? 78 | private static boolean isSorted(Comparable[] a) { 79 | return isSorted(a, 0, a.length - 1); 80 | } 81 | 82 | // is the array sorted from a[lo] to a[hi] 83 | private static boolean isSorted(Comparable[] a, int lo, int hi) { 84 | for (int i = lo + 1; i <= hi; i++) 85 | if (less(a[i], a[i-1])) return false; 86 | return true; 87 | } 88 | 89 | // is the array a[] sorted? 90 | private static boolean isSorted(Object[] a, Comparator comparator) { 91 | return isSorted(a, comparator, 0, a.length - 1); 92 | } 93 | 94 | // is the array sorted from a[lo] to a[hi] 95 | private static boolean isSorted(Object[] a, Comparator comparator, int lo, int hi) { 96 | for (int i = lo + 1; i <= hi; i++) 97 | if (less(comparator, a[i], a[i-1])) return false; 98 | return true; 99 | } 100 | 101 | 102 | 103 | // print array to standard output 104 | private static void show(Comparable[] a) { 105 | for (int i = 0; i < a.length; i++) { 106 | StdOut.println(a[i]); 107 | } 108 | } 109 | 110 | /** 111 | * Reads in a sequence of strings from standard input; selection sorts them; 112 | * and prints them to standard output in ascending order. 113 | * 114 | * @param args the command-line arguments 115 | */ 116 | public static void main(String[] args) { 117 | String[] a = StdIn.readAllStrings(); 118 | Selection.sort(a); 119 | show(a); 120 | } 121 | } -------------------------------------------------------------------------------- /Chapter 5 字符串 Strings/5.1 LSD radix sort.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code LSD} class provides static methods for sorting an 3 | * array of w-character strings or 32-bit integers using LSD radix sort. 4 | * @author Robert Sedgewick 5 | * @author Kevin Wayne 6 | */ 7 | public class LSD { 8 | private static final int BITS_PER_BYTE = 8; 9 | 10 | // do not instantiate 11 | private LSD() { } 12 | 13 | /** 14 | * Rearranges the array of W-character strings in ascending order. 15 | * 16 | * @param a the array to be sorted 17 | * @param w the number of characters per string 18 | */ 19 | public static void sort(String[] a, int w) { 20 | int n = a.length; 21 | int R = 256; // extend ASCII alphabet size 22 | String[] aux = new String[n]; 23 | 24 | for (int d = w-1; d >= 0; d--) { 25 | // sort by key-indexed counting on dth character 26 | 27 | // compute frequency counts 28 | int[] count = new int[R+1]; 29 | for (int i = 0; i < n; i++) 30 | count[a[i].charAt(d) + 1]++; 31 | 32 | // compute cumulates 33 | for (int r = 0; r < R; r++) 34 | count[r+1] += count[r]; 35 | 36 | // move data 37 | for (int i = 0; i < n; i++) 38 | aux[count[a[i].charAt(d)]++] = a[i]; 39 | 40 | // copy back 41 | for (int i = 0; i < n; i++) 42 | a[i] = aux[i]; 43 | } 44 | } 45 | 46 | /** 47 | * Rearranges the array of 32-bit integers in ascending order. 48 | * This is about 2-3x faster than Arrays.sort(). 49 | * 50 | * @param a the array to be sorted 51 | */ 52 | public static void sort(int[] a) { 53 | final int BITS = 32; // each int is 32 bits 54 | final int R = 1 << BITS_PER_BYTE; // each bytes is between 0 and 255 55 | final int MASK = R - 1; // 0xFF 56 | final int w = BITS / BITS_PER_BYTE; // each int is 4 bytes 57 | 58 | int n = a.length; 59 | int[] aux = new int[n]; 60 | 61 | for (int d = 0; d < w; d++) { 62 | 63 | // compute frequency counts 64 | int[] count = new int[R+1]; 65 | for (int i = 0; i < n; i++) { 66 | int c = (a[i] >> BITS_PER_BYTE*d) & MASK; 67 | count[c + 1]++; 68 | } 69 | 70 | // compute cumulates 71 | for (int r = 0; r < R; r++) 72 | count[r+1] += count[r]; 73 | 74 | // for most significant byte, 0x80-0xFF comes before 0x00-0x7F 75 | if (d == w-1) { 76 | int shift1 = count[R] - count[R/2]; 77 | int shift2 = count[R/2]; 78 | for (int r = 0; r < R/2; r++) 79 | count[r] += shift1; 80 | for (int r = R/2; r < R; r++) 81 | count[r] -= shift2; 82 | } 83 | 84 | // move data 85 | for (int i = 0; i < n; i++) { 86 | int c = (a[i] >> BITS_PER_BYTE*d) & MASK; 87 | aux[count[c]++] = a[i]; 88 | } 89 | 90 | // copy back 91 | for (int i = 0; i < n; i++) 92 | a[i] = aux[i]; 93 | } 94 | } 95 | 96 | /** 97 | * Reads in a sequence of fixed-length strings from standard input; 98 | * LSD radix sorts them; 99 | * and prints them to standard output in ascending order. 100 | * 101 | * @param args the command-line arguments 102 | */ 103 | public static void main(String[] args) { 104 | String[] a = StdIn.readAllStrings(); 105 | int n = a.length; 106 | 107 | // check that strings have fixed length 108 | int w = a[0].length(); 109 | for (int i = 0; i < n; i++) 110 | assert a[i].length() == w : "Strings must have fixed length"; 111 | 112 | // sort the strings 113 | sort(a, w); 114 | 115 | // print results 116 | for (int i = 0; i < n; i++) 117 | StdOut.println(a[i]); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-1.3 FIFO queue (linked list).java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.NoSuchElementException; 3 | 4 | public class LinkedQueue implements Iterable { 5 | private int n; 6 | private Node first; 7 | private Node last; 8 | 9 | private class Node { 10 | private Item item; 11 | private Node next; 12 | } 13 | 14 | public LinkedQueue() { 15 | first = null; 16 | last = null; 17 | n = 0; 18 | assert check(); 19 | } 20 | 21 | public boolean isEmpty() { 22 | return first == null; 23 | } 24 | 25 | public int size() { 26 | return n; 27 | } 28 | 29 | public Item peek() { 30 | if (isEmpty()) throw new NoSuchElementException("Queue underflow"); 31 | return first.item; 32 | } 33 | 34 | public void enqueue(Item item) { 35 | Node oldlast = last; 36 | last = new Node(); 37 | last.item = item; 38 | last.next = null; 39 | if (isEmpty()) first = last; 40 | else oldlast.next = last; 41 | n++; 42 | assert check(); 43 | } 44 | 45 | public Item dequeue() { 46 | if (isEmpty()) throw new NoSuchElementException("Queue underflow"); 47 | Item item = first.item; 48 | first = first.next; 49 | n--; 50 | if (isEmpty()) last = null; 51 | assert check(); 52 | return item; 53 | } 54 | 55 | public String toString() { 56 | StringBuilder s = new StringBuilder(); 57 | for (Item item : this) 58 | s.append(item + " "); 59 | return s.toString(); 60 | } 61 | 62 | private boolean check() { 63 | if (n < 0) { 64 | return false; 65 | } 66 | else if (n == 0) { 67 | if (first != null) return false; 68 | if (last != null) return false; 69 | } 70 | else if (n == 1) { 71 | if (first == null || last == null) return false; 72 | if (first != last) return false; 73 | if (first.next != null) return false; 74 | } 75 | else { 76 | if (first == null || last == null) return false; 77 | if (first == last) return false; 78 | if (first.next == null) return false; 79 | if (last.next != null) return false; 80 | 81 | int numberOfNodes = 0; 82 | for (Node x = first; x != null && numberOfNodes <= n; x = x.next) { 83 | numberOfNodes++; 84 | } 85 | if (numberOfNodes != n) return false; 86 | 87 | Node lastNode = first; 88 | while (lastNode.next != null) { 89 | lastNode = lastNode.next; 90 | } 91 | if (last != lastNode) return false; 92 | } 93 | 94 | return true; 95 | } 96 | 97 | 98 | public Iterator iterator() { 99 | return new ListIterator(); 100 | } 101 | 102 | private class ListIterator implements Iterator { 103 | private Node current = first; 104 | 105 | public boolean hasNext() { return current != null; } 106 | public void remove() { throw new UnsupportedOperationException(); } 107 | 108 | public Item next() { 109 | if (!hasNext()) throw new NoSuchElementException(); 110 | Item item = current.item; 111 | current = current.next; 112 | return item; 113 | } 114 | } 115 | 116 | 117 | public static void main(String[] args) { 118 | LinkedQueue queue = new LinkedQueue(); 119 | while (!StdIn.isEmpty()) { 120 | String item = StdIn.readString(); 121 | if (!item.equals("-")) 122 | queue.enqueue(item); 123 | else if (!queue.isEmpty()) 124 | StdOut.print(queue.dequeue() + " "); 125 | } 126 | StdOut.println("(" + queue.size() + " left on queue)"); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-6.3 suffix array (suffix sorting).java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class SuffixArray { 4 | private Suffix[] suffixes; 5 | 6 | public SuffixArray(String text) { 7 | int n = text.length(); 8 | this.suffixes = new Suffix[n]; 9 | for (int i = 0; i < n; i++) 10 | suffixes[i] = new Suffix(text, i); 11 | Arrays.sort(suffixes); 12 | } 13 | 14 | private static class Suffix implements Comparable { 15 | private final String text; 16 | private final int index; 17 | 18 | private Suffix(String text, int index) { 19 | this.text = text; 20 | this.index = index; 21 | } 22 | private int length() { 23 | return text.length() - index; 24 | } 25 | private char charAt(int i) { 26 | return text.charAt(index + i); 27 | } 28 | 29 | public int compareTo(Suffix that) { 30 | if (this == that) return 0; 31 | int n = Math.min(this.length(), that.length()); 32 | for (int i = 0; i < n; i++) { 33 | if (this.charAt(i) < that.charAt(i)) return -1; 34 | if (this.charAt(i) > that.charAt(i)) return +1; 35 | } 36 | return this.length() - that.length(); 37 | } 38 | 39 | public String toString() { 40 | return text.substring(index); 41 | } 42 | } 43 | 44 | public int length() { 45 | return suffixes.length; 46 | } 47 | 48 | 49 | public int index(int i) { 50 | if (i < 0 || i >= suffixes.length) throw new IndexOutOfBoundsException(); 51 | return suffixes[i].index; 52 | } 53 | 54 | 55 | public int lcp(int i) { 56 | if (i < 1 || i >= suffixes.length) throw new IndexOutOfBoundsException(); 57 | return lcp(suffixes[i], suffixes[i-1]); 58 | } 59 | 60 | private static int lcp(Suffix s, Suffix t) { 61 | int n = Math.min(s.length(), t.length()); 62 | for (int i = 0; i < n; i++) { 63 | if (s.charAt(i) != t.charAt(i)) return i; 64 | } 65 | return n; 66 | } 67 | 68 | public String select(int i) { 69 | if (i < 0 || i >= suffixes.length) throw new IndexOutOfBoundsException(); 70 | return suffixes[i].toString(); 71 | } 72 | 73 | public int rank(String query) { 74 | int lo = 0, hi = suffixes.length - 1; 75 | while (lo <= hi) { 76 | int mid = lo + (hi - lo) / 2; 77 | int cmp = compare(query, suffixes[mid]); 78 | if (cmp < 0) hi = mid - 1; 79 | else if (cmp > 0) lo = mid + 1; 80 | else return mid; 81 | } 82 | return lo; 83 | } 84 | 85 | private static int compare(String query, Suffix suffix) { 86 | int n = Math.min(query.length(), suffix.length()); 87 | for (int i = 0; i < n; i++) { 88 | if (query.charAt(i) < suffix.charAt(i)) return -1; 89 | if (query.charAt(i) > suffix.charAt(i)) return +1; 90 | } 91 | return query.length() - suffix.length(); 92 | } 93 | 94 | public static void main(String[] args) { 95 | String s = StdIn.readAll().replaceAll("\\s+", " ").trim(); 96 | SuffixArray suffix = new SuffixArray(s); 97 | 98 | 99 | StdOut.println(" i ind lcp rnk select"); 100 | StdOut.println("---------------------------"); 101 | 102 | for (int i = 0; i < s.length(); i++) { 103 | int index = suffix.index(i); 104 | String ith = "\"" + s.substring(index, Math.min(index + 50, s.length())) + "\""; 105 | assert s.substring(index).equals(suffix.select(i)); 106 | int rank = suffix.rank(s.substring(index)); 107 | if (i == 0) { 108 | StdOut.printf("%3d %3d %3s %3d %s\n", i, index, "-", rank, ith); 109 | } 110 | else { 111 | int lcp = suffix.lcp(i); 112 | StdOut.printf("%3d %3d %3d %3d %s\n", i, index, lcp, rank, ith); 113 | } 114 | } 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.7 MST (Prim).java: -------------------------------------------------------------------------------- 1 | public class PrimMST { 2 | private static final double FLOATING_POINT_EPSILON = 1E-12; 3 | 4 | private Edge[] edgeTo; 5 | private double[] distTo; 6 | private boolean[] marked; 7 | private IndexMinPQ pq; 8 | 9 | public PrimMST(EdgeWeightedGraph G) { 10 | edgeTo = new Edge[G.V()]; 11 | distTo = new double[G.V()]; 12 | marked = new boolean[G.V()]; 13 | pq = new IndexMinPQ(G.V()); 14 | for (int v = 0; v < G.V(); v++) 15 | distTo[v] = Double.POSITIVE_INFINITY; 16 | 17 | for (int v = 0; v < G.V(); v++) 18 | if (!marked[v]) prim(G, v); 19 | 20 | assert check(G); 21 | } 22 | 23 | private void prim(EdgeWeightedGraph G, int s) { 24 | distTo[s] = 0.0; 25 | pq.insert(s, distTo[s]); 26 | while (!pq.isEmpty()) { 27 | int v = pq.delMin(); 28 | scan(G, v); 29 | } 30 | } 31 | 32 | private void scan(EdgeWeightedGraph G, int v) { 33 | marked[v] = true; 34 | for (Edge e : G.adj(v)) { 35 | int w = e.other(v); 36 | if (marked[w]) continue; 37 | if (e.weight() < distTo[w]) { 38 | distTo[w] = e.weight(); 39 | edgeTo[w] = e; 40 | if (pq.contains(w)) pq.decreaseKey(w, distTo[w]); 41 | else pq.insert(w, distTo[w]); 42 | } 43 | } 44 | } 45 | 46 | public Iterable edges() { 47 | Queue mst = new Queue(); 48 | for (int v = 0; v < edgeTo.length; v++) { 49 | Edge e = edgeTo[v]; 50 | if (e != null) { 51 | mst.enqueue(e); 52 | } 53 | } 54 | return mst; 55 | } 56 | 57 | public double weight() { 58 | double weight = 0.0; 59 | for (Edge e : edges()) 60 | weight += e.weight(); 61 | return weight; 62 | } 63 | 64 | 65 | private boolean check(EdgeWeightedGraph G) { 66 | 67 | double totalWeight = 0.0; 68 | for (Edge e : edges()) { 69 | totalWeight += e.weight(); 70 | } 71 | if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) { 72 | System.err.printf("Weight of edges does not equal weight(): %f vs. %f\n", totalWeight, weight()); 73 | return false; 74 | } 75 | 76 | UF uf = new UF(G.V()); 77 | for (Edge e : edges()) { 78 | int v = e.either(), w = e.other(v); 79 | if (uf.connected(v, w)) { 80 | System.err.println("Not a forest"); 81 | return false; 82 | } 83 | uf.union(v, w); 84 | } 85 | 86 | for (Edge e : G.edges()) { 87 | int v = e.either(), w = e.other(v); 88 | if (!uf.connected(v, w)) { 89 | System.err.println("Not a spanning forest"); 90 | return false; 91 | } 92 | } 93 | 94 | for (Edge e : edges()) { 95 | 96 | uf = new UF(G.V()); 97 | for (Edge f : edges()) { 98 | int x = f.either(), y = f.other(x); 99 | if (f != e) uf.union(x, y); 100 | } 101 | 102 | for (Edge f : G.edges()) { 103 | int x = f.either(), y = f.other(x); 104 | if (!uf.connected(x, y)) { 105 | if (f.weight() < e.weight()) { 106 | System.err.println("Edge " + f + " violates cut optimality conditions"); 107 | return false; 108 | } 109 | } 110 | } 111 | 112 | } 113 | 114 | return true; 115 | } 116 | 117 | public static void main(String[] args) { 118 | In in = new In(args[0]); 119 | EdgeWeightedGraph G = new EdgeWeightedGraph(in); 120 | PrimMST mst = new PrimMST(G); 121 | for (Edge e : mst.edges()) { 122 | StdOut.println(e); 123 | } 124 | StdOut.printf("%.5f\n", mst.weight()); 125 | } 126 | 127 | 128 | } 129 | -------------------------------------------------------------------------------- /Chapter 5 字符串 Strings/5.8 substring search (Rabin–Karp).java: -------------------------------------------------------------------------------- 1 | import java.math.BigInteger; 2 | import java.util.Random; 3 | 4 | /** 5 | * The {@code RabinKarp} class finds the first occurrence of a pattern string 6 | * in a text string. 7 | * This implementation uses the Rabin-Karp algorithm. 8 | */ 9 | public class RabinKarp { 10 | private String pat; // the pattern // needed only for Las Vegas 11 | private long patHash; // pattern hash value 12 | private int m; // pattern length 13 | private long q; // a large prime, small enough to avoid long overflow 14 | private int R; // radix 15 | private long RM; // R^(M-1) % Q 16 | 17 | /** 18 | * Preprocesses the pattern string. 19 | * 20 | * @param pattern the pattern string 21 | * @param R the alphabet size 22 | */ 23 | public RabinKarp(char[] pattern, int R) { 24 | this.pat = String.valueOf(pattern); 25 | this.R = R; 26 | throw new UnsupportedOperationException("Operation not supported yet"); 27 | } 28 | 29 | /** 30 | * Preprocesses the pattern string. 31 | * 32 | * @param pat the pattern string 33 | */ 34 | public RabinKarp(String pat) { 35 | this.pat = pat; // save pattern (needed only for Las Vegas) 36 | R = 256; 37 | m = pat.length(); 38 | q = longRandomPrime(); 39 | 40 | // precompute R^(m-1) % q for use in removing leading digit 41 | RM = 1; 42 | for (int i = 1; i <= m-1; i++) 43 | RM = (R * RM) % q; 44 | patHash = hash(pat, m); 45 | } 46 | 47 | // Compute hash for key[0..m-1]. 48 | private long hash(String key, int m) { 49 | long h = 0; 50 | for (int j = 0; j < m; j++) 51 | h = (R * h + key.charAt(j)) % q; 52 | return h; 53 | } 54 | 55 | // Las Vegas version: does pat[] match txt[i..i-m+1] ? 56 | private boolean check(String txt, int i) { 57 | for (int j = 0; j < m; j++) 58 | if (pat.charAt(j) != txt.charAt(i + j)) 59 | return false; 60 | return true; 61 | } 62 | 63 | // Monte Carlo version: always return true 64 | // private boolean check(int i) { 65 | // return true; 66 | //} 67 | 68 | /** 69 | * Returns the index of the first occurrrence of the pattern string 70 | * in the text string. 71 | * 72 | * @param txt the text string 73 | * @return the index of the first occurrence of the pattern string 74 | * in the text string; n if no such match 75 | */ 76 | public int search(String txt) { 77 | int n = txt.length(); 78 | if (n < m) return n; 79 | long txtHash = hash(txt, m); 80 | 81 | // check for match at offset 0 82 | if ((patHash == txtHash) && check(txt, 0)) 83 | return 0; 84 | 85 | // check for hash match; if hash match, check for exact match 86 | for (int i = m; i < n; i++) { 87 | // Remove leading digit, add trailing digit, check for match. 88 | txtHash = (txtHash + q - RM*txt.charAt(i-m) % q) % q; 89 | txtHash = (txtHash*R + txt.charAt(i)) % q; 90 | 91 | // match 92 | int offset = i - m + 1; 93 | if ((patHash == txtHash) && check(txt, offset)) 94 | return offset; 95 | } 96 | 97 | // no match 98 | return n; 99 | } 100 | 101 | 102 | // a random 31-bit prime 103 | private static long longRandomPrime() { 104 | BigInteger prime = BigInteger.probablePrime(31, new Random()); 105 | return prime.longValue(); 106 | } 107 | 108 | /** 109 | * Takes a pattern string and an input string as command-line arguments; 110 | * searches for the pattern string in the text string; and prints 111 | * the first occurrence of the pattern string in the text string. 112 | * 113 | * @param args the command-line arguments 114 | */ 115 | public static void main(String[] args) { 116 | String pat = args[0]; 117 | String txt = args[1]; 118 | 119 | RabinKarp searcher = new RabinKarp(pat); 120 | int offset = searcher.search(txt); 121 | 122 | // print results 123 | StdOut.println("text: " + txt); 124 | 125 | // from brute force search method 1 126 | StdOut.print("pattern: "); 127 | for (int i = 0; i < offset; i++) 128 | StdOut.print(" "); 129 | StdOut.println(pat); 130 | } 131 | } -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-3.6 linear probing hash table.java: -------------------------------------------------------------------------------- 1 | public class LinearProbingHashST { 2 | private static final int INIT_CAPACITY = 4; 3 | 4 | private int n; 5 | private int m; 6 | private Key[] keys; 7 | private Value[] vals; 8 | 9 | 10 | public LinearProbingHashST() { 11 | this(INIT_CAPACITY); 12 | } 13 | 14 | public LinearProbingHashST(int capacity) { 15 | m = capacity; 16 | n = 0; 17 | keys = (Key[]) new Object[m]; 18 | vals = (Value[]) new Object[m]; 19 | } 20 | 21 | public int size() { 22 | return n; 23 | } 24 | 25 | public boolean isEmpty() { 26 | return size() == 0; 27 | } 28 | 29 | public boolean contains(Key key) { 30 | if (key == null) throw new IllegalArgumentException("argument to contains() is null"); 31 | return get(key) != null; 32 | } 33 | 34 | private int hash(Key key) { 35 | return (key.hashCode() & 0x7fffffff) % m; 36 | } 37 | 38 | private void resize(int capacity) { 39 | LinearProbingHashST temp = new LinearProbingHashST(capacity); 40 | for (int i = 0; i < m; i++) { 41 | if (keys[i] != null) { 42 | temp.put(keys[i], vals[i]); 43 | } 44 | } 45 | keys = temp.keys; 46 | vals = temp.vals; 47 | m = temp.m; 48 | } 49 | 50 | public void put(Key key, Value val) { 51 | if (key == null) throw new IllegalArgumentException("first argument to put() is null"); 52 | 53 | if (val == null) { 54 | delete(key); 55 | return; 56 | } 57 | 58 | if (n >= m/2) resize(2*m); 59 | 60 | int i; 61 | for (i = hash(key); keys[i] != null; i = (i + 1) % m) { 62 | if (keys[i].equals(key)) { 63 | vals[i] = val; 64 | return; 65 | } 66 | } 67 | keys[i] = key; 68 | vals[i] = val; 69 | n++; 70 | } 71 | 72 | public Value get(Key key) { 73 | if (key == null) throw new IllegalArgumentException("argument to get() is null"); 74 | for (int i = hash(key); keys[i] != null; i = (i + 1) % m) 75 | if (keys[i].equals(key)) 76 | return vals[i]; 77 | return null; 78 | } 79 | 80 | public void delete(Key key) { 81 | if (key == null) throw new IllegalArgumentException("argument to delete() is null"); 82 | if (!contains(key)) return; 83 | 84 | int i = hash(key); 85 | while (!key.equals(keys[i])) { 86 | i = (i + 1) % m; 87 | } 88 | 89 | keys[i] = null; 90 | vals[i] = null; 91 | 92 | i = (i + 1) % m; 93 | while (keys[i] != null) { 94 | Key keyToRehash = keys[i]; 95 | Value valToRehash = vals[i]; 96 | keys[i] = null; 97 | vals[i] = null; 98 | n--; 99 | put(keyToRehash, valToRehash); 100 | i = (i + 1) % m; 101 | } 102 | 103 | n--; 104 | 105 | if (n > 0 && n <= m/8) resize(m/2); 106 | 107 | assert check(); 108 | } 109 | 110 | public Iterable keys() { 111 | Queue queue = new Queue(); 112 | for (int i = 0; i < m; i++) 113 | if (keys[i] != null) queue.enqueue(keys[i]); 114 | return queue; 115 | } 116 | 117 | private boolean check() { 118 | 119 | if (m < 2*n) { 120 | System.err.println("Hash table size m = " + m + "; array size n = " + n); 121 | return false; 122 | } 123 | 124 | for (int i = 0; i < m; i++) { 125 | if (keys[i] == null) continue; 126 | else if (get(keys[i]) != vals[i]) { 127 | System.err.println("get[" + keys[i] + "] = " + get(keys[i]) + "; vals[i] = " + vals[i]); 128 | return false; 129 | } 130 | } 131 | return true; 132 | } 133 | 134 | 135 | public static void main(String[] args) { 136 | LinearProbingHashST st = new LinearProbingHashST(); 137 | for (int i = 0; !StdIn.isEmpty(); i++) { 138 | String key = StdIn.readString(); 139 | st.put(key, i); 140 | } 141 | 142 | for (String s : st.keys()) 143 | StdOut.println(s + " " + st.get(s)); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.10 data compression (Huffman).java: -------------------------------------------------------------------------------- 1 | public class Huffman { 2 | 3 | private static final int R = 256; 4 | 5 | private Huffman() { } 6 | 7 | private static class Node implements Comparable { 8 | private final char ch; 9 | private final int freq; 10 | private final Node left, right; 11 | 12 | Node(char ch, int freq, Node left, Node right) { 13 | this.ch = ch; 14 | this.freq = freq; 15 | this.left = left; 16 | this.right = right; 17 | } 18 | 19 | private boolean isLeaf() { 20 | assert ((left == null) && (right == null)) || ((left != null) && (right != null)); 21 | return (left == null) && (right == null); 22 | } 23 | 24 | public int compareTo(Node that) { 25 | return this.freq - that.freq; 26 | } 27 | } 28 | 29 | public static void compress() { 30 | String s = BinaryStdIn.readString(); 31 | char[] input = s.toCharArray(); 32 | 33 | int[] freq = new int[R]; 34 | for (int i = 0; i < input.length; i++) 35 | freq[input[i]]++; 36 | 37 | Node root = buildTrie(freq); 38 | 39 | String[] st = new String[R]; 40 | buildCode(st, root, ""); 41 | 42 | writeTrie(root); 43 | 44 | BinaryStdOut.write(input.length); 45 | 46 | for (int i = 0; i < input.length; i++) { 47 | String code = st[input[i]]; 48 | for (int j = 0; j < code.length(); j++) { 49 | if (code.charAt(j) == '0') { 50 | BinaryStdOut.write(false); 51 | } 52 | else if (code.charAt(j) == '1') { 53 | BinaryStdOut.write(true); 54 | } 55 | else throw new IllegalStateException("Illegal state"); 56 | } 57 | } 58 | 59 | BinaryStdOut.close(); 60 | } 61 | 62 | private static Node buildTrie(int[] freq) { 63 | 64 | MinPQ pq = new MinPQ(); 65 | for (char i = 0; i < R; i++) 66 | if (freq[i] > 0) 67 | pq.insert(new Node(i, freq[i], null, null)); 68 | 69 | if (pq.size() == 1) { 70 | if (freq['\0'] == 0) pq.insert(new Node('\0', 0, null, null)); 71 | else pq.insert(new Node('\1', 0, null, null)); 72 | } 73 | 74 | while (pq.size() > 1) { 75 | Node left = pq.delMin(); 76 | Node right = pq.delMin(); 77 | Node parent = new Node('\0', left.freq + right.freq, left, right); 78 | pq.insert(parent); 79 | } 80 | return pq.delMin(); 81 | } 82 | 83 | 84 | private static void writeTrie(Node x) { 85 | if (x.isLeaf()) { 86 | BinaryStdOut.write(true); 87 | BinaryStdOut.write(x.ch, 8); 88 | return; 89 | } 90 | BinaryStdOut.write(false); 91 | writeTrie(x.left); 92 | writeTrie(x.right); 93 | } 94 | 95 | private static void buildCode(String[] st, Node x, String s) { 96 | if (!x.isLeaf()) { 97 | buildCode(st, x.left, s + '0'); 98 | buildCode(st, x.right, s + '1'); 99 | } 100 | else { 101 | st[x.ch] = s; 102 | } 103 | } 104 | 105 | public static void expand() { 106 | 107 | Node root = readTrie(); 108 | 109 | int length = BinaryStdIn.readInt(); 110 | 111 | for (int i = 0; i < length; i++) { 112 | Node x = root; 113 | while (!x.isLeaf()) { 114 | boolean bit = BinaryStdIn.readBoolean(); 115 | if (bit) x = x.right; 116 | else x = x.left; 117 | } 118 | BinaryStdOut.write(x.ch, 8); 119 | } 120 | BinaryStdOut.close(); 121 | } 122 | 123 | 124 | private static Node readTrie() { 125 | boolean isLeaf = BinaryStdIn.readBoolean(); 126 | if (isLeaf) { 127 | return new Node(BinaryStdIn.readChar(), -1, null, null); 128 | } 129 | else { 130 | return new Node('\0', -1, readTrie(), readTrie()); 131 | } 132 | } 133 | 134 | public static void main(String[] args) { 135 | if (args[0].equals("-")) compress(); 136 | else if (args[0].equals("+")) expand(); 137 | else throw new IllegalArgumentException("Illegal command line argument"); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.2 MSD radix sort.java: -------------------------------------------------------------------------------- 1 | public class MSD { 2 | private static final int BITS_PER_BYTE = 8; 3 | private static final int BITS_PER_INT = 32; 4 | private static final int R = 256; 5 | private static final int CUTOFF = 15; 6 | 7 | private MSD() { } 8 | 9 | public static void sort(String[] a) { 10 | int n = a.length; 11 | String[] aux = new String[n]; 12 | sort(a, 0, n-1, 0, aux); 13 | } 14 | 15 | private static int charAt(String s, int d) { 16 | assert d >= 0 && d <= s.length(); 17 | if (d == s.length()) return -1; 18 | return s.charAt(d); 19 | } 20 | 21 | private static void sort(String[] a, int lo, int hi, int d, String[] aux) { 22 | 23 | if (hi <= lo + CUTOFF) { 24 | insertion(a, lo, hi, d); 25 | return; 26 | } 27 | 28 | int[] count = new int[R+2]; 29 | for (int i = lo; i <= hi; i++) { 30 | int c = charAt(a[i], d); 31 | count[c+2]++; 32 | } 33 | 34 | for (int r = 0; r < R+1; r++) 35 | count[r+1] += count[r]; 36 | 37 | for (int i = lo; i <= hi; i++) { 38 | int c = charAt(a[i], d); 39 | aux[count[c+1]++] = a[i]; 40 | } 41 | 42 | for (int i = lo; i <= hi; i++) 43 | a[i] = aux[i - lo]; 44 | 45 | 46 | for (int r = 0; r < R; r++) 47 | sort(a, lo + count[r], lo + count[r+1] - 1, d+1, aux); 48 | } 49 | 50 | 51 | private static void insertion(String[] a, int lo, int hi, int d) { 52 | for (int i = lo; i <= hi; i++) 53 | for (int j = i; j > lo && less(a[j], a[j-1], d); j--) 54 | exch(a, j, j-1); 55 | } 56 | 57 | private static void exch(String[] a, int i, int j) { 58 | String temp = a[i]; 59 | a[i] = a[j]; 60 | a[j] = temp; 61 | } 62 | 63 | private static boolean less(String v, String w, int d) { 64 | for (int i = d; i < Math.min(v.length(), w.length()); i++) { 65 | if (v.charAt(i) < w.charAt(i)) return true; 66 | if (v.charAt(i) > w.charAt(i)) return false; 67 | } 68 | return v.length() < w.length(); 69 | } 70 | 71 | 72 | public static void sort(int[] a) { 73 | int n = a.length; 74 | int[] aux = new int[n]; 75 | sort(a, 0, n-1, 0, aux); 76 | } 77 | 78 | private static void sort(int[] a, int lo, int hi, int d, int[] aux) { 79 | 80 | if (hi <= lo + CUTOFF) { 81 | insertion(a, lo, hi, d); 82 | return; 83 | } 84 | 85 | int[] count = new int[R+1]; 86 | int mask = R - 1; 87 | int shift = BITS_PER_INT - BITS_PER_BYTE*d - BITS_PER_BYTE; 88 | for (int i = lo; i <= hi; i++) { 89 | int c = (a[i] >> shift) & mask; 90 | count[c + 1]++; 91 | } 92 | 93 | for (int r = 0; r < R; r++) 94 | count[r+1] += count[r]; 95 | 96 | if (d == 0) { 97 | int shift1 = count[R] - count[R/2]; 98 | int shift2 = count[R/2]; 99 | for (int r = 0; r < R/2; r++) 100 | count[r] += shift1; 101 | for (int r = R/2; r < R; r++) 102 | count[r] -= shift2; 103 | } 104 | for (int i = lo; i <= hi; i++) { 105 | int c = (a[i] >> shift) & mask; 106 | aux[count[c]++] = a[i]; 107 | } 108 | 109 | for (int i = lo; i <= hi; i++) 110 | a[i] = aux[i - lo]; 111 | 112 | if (d == 4) return; 113 | 114 | if (count[0] > 0) 115 | sort(a, lo, lo + count[0] - 1, d+1, aux); 116 | for (int r = 0; r < R; r++) 117 | if (count[r+1] > count[r]) 118 | sort(a, lo + count[r], lo + count[r+1] - 1, d+1, aux); 119 | } 120 | 121 | private static void insertion(int[] a, int lo, int hi, int d) { 122 | for (int i = lo; i <= hi; i++) 123 | for (int j = i; j > lo && a[j] < a[j-1]; j--) 124 | exch(a, j, j-1); 125 | } 126 | 127 | private static void exch(int[] a, int i, int j) { 128 | int temp = a[i]; 129 | a[i] = a[j]; 130 | a[j] = temp; 131 | } 132 | 133 | 134 | public static void main(String[] args) { 135 | String[] a = StdIn.readAllStrings(); 136 | int n = a.length; 137 | sort(a); 138 | for (int i = 0; i < n; i++) 139 | StdOut.println(a[i]); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Chapter 4 图 Graph/4.4 depth-first search in a digraph.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code DirectedDFS} class represents a data type for 3 | * determining the vertices reachable from a given source vertex s 4 | * (or set of source vertices) in a digraph. For versions that find the paths, 5 | * see {@link DepthFirstDirectedPaths} and {@link BreadthFirstDirectedPaths}. 6 | * This implementation uses depth-first search. 7 | * The constructor takes time proportional to V + E 8 | * (in the worst case), 9 | * where V is the number of vertices and E is the number of edges. 10 | * @author Robert Sedgewick 11 | * @author Kevin Wayne 12 | */ 13 | public class DirectedDFS { 14 | private boolean[] marked; // marked[v] = true if v is reachable 15 | // from source (or sources) 16 | private int count; // number of vertices reachable from s 17 | 18 | /** 19 | * Computes the vertices in digraph {@code G} that are 20 | * reachable from the source vertex {@code s}. 21 | * @param G the digraph 22 | * @param s the source vertex 23 | * @throws IllegalArgumentException unless {@code 0 <= s < V} 24 | */ 25 | public DirectedDFS(Digraph G, int s) { 26 | marked = new boolean[G.V()]; 27 | validateVertex(s); 28 | dfs(G, s); 29 | } 30 | 31 | /** 32 | * Computes the vertices in digraph {@code G} that are 33 | * connected to any of the source vertices {@code sources}. 34 | * @param G the graph 35 | * @param sources the source vertices 36 | * @throws IllegalArgumentException unless {@code 0 <= s < V} 37 | * for each vertex {@code s} in {@code sources} 38 | */ 39 | public DirectedDFS(Digraph G, Iterable sources) { 40 | marked = new boolean[G.V()]; 41 | validateVertices(sources); 42 | for (int v : sources) { 43 | if (!marked[v]) dfs(G, v); 44 | } 45 | } 46 | 47 | private void dfs(Digraph G, int v) { 48 | count++; 49 | marked[v] = true; 50 | for (int w : G.adj(v)) { 51 | if (!marked[w]) dfs(G, w); 52 | } 53 | } 54 | 55 | /** 56 | * Is there a directed path from the source vertex (or any 57 | * of the source vertices) and vertex {@code v}? 58 | * @param v the vertex 59 | * @return {@code true} if there is a directed path, {@code false} otherwise 60 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 61 | */ 62 | public boolean marked(int v) { 63 | validateVertex(v); 64 | return marked[v]; 65 | } 66 | 67 | /** 68 | * Returns the number of vertices reachable from the source vertex 69 | * (or source vertices). 70 | * @return the number of vertices reachable from the source vertex 71 | * (or source vertices) 72 | */ 73 | public int count() { 74 | return count; 75 | } 76 | 77 | // throw an IllegalArgumentException unless {@code 0 <= v < V} 78 | private void validateVertex(int v) { 79 | int V = marked.length; 80 | if (v < 0 || v >= V) 81 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 82 | } 83 | 84 | // throw an IllegalArgumentException unless {@code 0 <= v < V} 85 | private void validateVertices(Iterable vertices) { 86 | if (vertices == null) { 87 | throw new IllegalArgumentException("argument is null"); 88 | } 89 | int V = marked.length; 90 | for (int v : vertices) { 91 | if (v < 0 || v >= V) { 92 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 93 | } 94 | } 95 | } 96 | 97 | 98 | /** 99 | * Unit tests the {@code DirectedDFS} data type. 100 | * 101 | * @param args the command-line arguments 102 | */ 103 | public static void main(String[] args) { 104 | 105 | // read in digraph from command-line argument 106 | In in = new In(args[0]); 107 | Digraph G = new Digraph(in); 108 | 109 | // read in sources from command-line arguments 110 | Bag sources = new Bag(); 111 | for (int i = 1; i < args.length; i++) { 112 | int s = Integer.parseInt(args[i]); 113 | sources.add(s); 114 | } 115 | 116 | // multiple-source reachability 117 | DirectedDFS dfs = new DirectedDFS(G, sources); 118 | 119 | // print out vertices reachable from sources 120 | for (int v = 0; v < G.V(); v++) { 121 | if (dfs.marked(v)) StdOut.print(v + " "); 122 | } 123 | StdOut.println(); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /Chapter 5 字符串 Strings/5.7 substring search (Boyer–Moore).java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code BoyerMoore} class finds the first occurrence of a pattern string 3 | * in a text string. 4 | * This implementation uses the Boyer-Moore algorithm (with the bad-character 5 | * rule, but not the strong good suffix rule). 6 | */ 7 | public class BoyerMoore { 8 | private final int R; // the radix 9 | private int[] right; // the bad-character skip array 10 | 11 | private char[] pattern; // store the pattern as a character array 12 | private String pat; // or as a string 13 | 14 | /** 15 | * Preprocesses the pattern string. 16 | * 17 | * @param pat the pattern string 18 | */ 19 | public BoyerMoore(String pat) { 20 | this.R = 256; 21 | this.pat = pat; 22 | 23 | // position of rightmost occurrence of c in the pattern 24 | right = new int[R]; 25 | for (int c = 0; c < R; c++) 26 | right[c] = -1; 27 | for (int j = 0; j < pat.length(); j++) 28 | right[pat.charAt(j)] = j; 29 | } 30 | 31 | /** 32 | * Preprocesses the pattern string. 33 | * 34 | * @param pattern the pattern string 35 | * @param R the alphabet size 36 | */ 37 | public BoyerMoore(char[] pattern, int R) { 38 | this.R = R; 39 | this.pattern = new char[pattern.length]; 40 | for (int j = 0; j < pattern.length; j++) 41 | this.pattern[j] = pattern[j]; 42 | 43 | // position of rightmost occurrence of c in the pattern 44 | right = new int[R]; 45 | for (int c = 0; c < R; c++) 46 | right[c] = -1; 47 | for (int j = 0; j < pattern.length; j++) 48 | right[pattern[j]] = j; 49 | } 50 | 51 | /** 52 | * Returns the index of the first occurrrence of the pattern string 53 | * in the text string. 54 | * 55 | * @param txt the text string 56 | * @return the index of the first occurrence of the pattern string 57 | * in the text string; n if no such match 58 | */ 59 | public int search(String txt) { 60 | int m = pat.length(); 61 | int n = txt.length(); 62 | int skip; 63 | for (int i = 0; i <= n - m; i += skip) { 64 | skip = 0; 65 | for (int j = m-1; j >= 0; j--) { 66 | if (pat.charAt(j) != txt.charAt(i+j)) { 67 | skip = Math.max(1, j - right[txt.charAt(i+j)]); 68 | break; 69 | } 70 | } 71 | if (skip == 0) return i; // found 72 | } 73 | return n; // not found 74 | } 75 | 76 | 77 | /** 78 | * Returns the index of the first occurrrence of the pattern string 79 | * in the text string. 80 | * 81 | * @param text the text string 82 | * @return the index of the first occurrence of the pattern string 83 | * in the text string; n if no such match 84 | */ 85 | public int search(char[] text) { 86 | int m = pattern.length; 87 | int n = text.length; 88 | int skip; 89 | for (int i = 0; i <= n - m; i += skip) { 90 | skip = 0; 91 | for (int j = m-1; j >= 0; j--) { 92 | if (pattern[j] != text[i+j]) { 93 | skip = Math.max(1, j - right[text[i+j]]); 94 | break; 95 | } 96 | } 97 | if (skip == 0) return i; // found 98 | } 99 | return n; // not found 100 | } 101 | 102 | 103 | /** 104 | * Takes a pattern string and an input string as command-line arguments; 105 | * searches for the pattern string in the text string; and prints 106 | * the first occurrence of the pattern string in the text string. 107 | * 108 | * @param args the command-line arguments 109 | */ 110 | public static void main(String[] args) { 111 | String pat = args[0]; 112 | String txt = args[1]; 113 | char[] pattern = pat.toCharArray(); 114 | char[] text = txt.toCharArray(); 115 | 116 | BoyerMoore boyermoore1 = new BoyerMoore(pat); 117 | BoyerMoore boyermoore2 = new BoyerMoore(pattern, 256); 118 | int offset1 = boyermoore1.search(txt); 119 | int offset2 = boyermoore2.search(text); 120 | 121 | // print results 122 | StdOut.println("text: " + txt); 123 | 124 | StdOut.print("pattern: "); 125 | for (int i = 0; i < offset1; i++) 126 | StdOut.print(" "); 127 | StdOut.println(pat); 128 | 129 | StdOut.print("pattern: "); 130 | for (int i = 0; i < offset2; i++) 131 | StdOut.print(" "); 132 | StdOut.println(pat); 133 | } 134 | } -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.9 shortest paths (Dijkstra).java: -------------------------------------------------------------------------------- 1 | public class DijkstraSP { 2 | private double[] distTo; 3 | private DirectedEdge[] edgeTo; 4 | private IndexMinPQ pq; 5 | 6 | public DijkstraSP(EdgeWeightedDigraph G, int s) { 7 | for (DirectedEdge e : G.edges()) { 8 | if (e.weight() < 0) 9 | throw new IllegalArgumentException("edge " + e + " has negative weight"); 10 | } 11 | 12 | distTo = new double[G.V()]; 13 | edgeTo = new DirectedEdge[G.V()]; 14 | 15 | validateVertex(s); 16 | 17 | for (int v = 0; v < G.V(); v++) 18 | distTo[v] = Double.POSITIVE_INFINITY; 19 | distTo[s] = 0.0; 20 | 21 | pq = new IndexMinPQ(G.V()); 22 | pq.insert(s, distTo[s]); 23 | while (!pq.isEmpty()) { 24 | int v = pq.delMin(); 25 | for (DirectedEdge e : G.adj(v)) 26 | relax(e); 27 | } 28 | 29 | assert check(G, s); 30 | } 31 | 32 | private void relax(DirectedEdge e) { 33 | int v = e.from(), w = e.to(); 34 | if (distTo[w] > distTo[v] + e.weight()) { 35 | distTo[w] = distTo[v] + e.weight(); 36 | edgeTo[w] = e; 37 | if (pq.contains(w)) pq.decreaseKey(w, distTo[w]); 38 | else pq.insert(w, distTo[w]); 39 | } 40 | } 41 | 42 | public double distTo(int v) { 43 | validateVertex(v); 44 | return distTo[v]; 45 | } 46 | 47 | public boolean hasPathTo(int v) { 48 | validateVertex(v); 49 | return distTo[v] < Double.POSITIVE_INFINITY; 50 | } 51 | 52 | public Iterable pathTo(int v) { 53 | validateVertex(v); 54 | if (!hasPathTo(v)) return null; 55 | Stack path = new Stack(); 56 | for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) { 57 | path.push(e); 58 | } 59 | return path; 60 | } 61 | 62 | 63 | private boolean check(EdgeWeightedDigraph G, int s) { 64 | 65 | for (DirectedEdge e : G.edges()) { 66 | if (e.weight() < 0) { 67 | System.err.println("negative edge weight detected"); 68 | return false; 69 | } 70 | } 71 | 72 | if (distTo[s] != 0.0 || edgeTo[s] != null) { 73 | System.err.println("distTo[s] and edgeTo[s] inconsistent"); 74 | return false; 75 | } 76 | for (int v = 0; v < G.V(); v++) { 77 | if (v == s) continue; 78 | if (edgeTo[v] == null && distTo[v] != Double.POSITIVE_INFINITY) { 79 | System.err.println("distTo[] and edgeTo[] inconsistent"); 80 | return false; 81 | } 82 | } 83 | 84 | for (int v = 0; v < G.V(); v++) { 85 | for (DirectedEdge e : G.adj(v)) { 86 | int w = e.to(); 87 | if (distTo[v] + e.weight() < distTo[w]) { 88 | System.err.println("edge " + e + " not relaxed"); 89 | return false; 90 | } 91 | } 92 | } 93 | 94 | for (int w = 0; w < G.V(); w++) { 95 | if (edgeTo[w] == null) continue; 96 | DirectedEdge e = edgeTo[w]; 97 | int v = e.from(); 98 | if (w != e.to()) return false; 99 | if (distTo[v] + e.weight() != distTo[w]) { 100 | System.err.println("edge " + e + " on shortest path not tight"); 101 | return false; 102 | } 103 | } 104 | return true; 105 | } 106 | 107 | private void validateVertex(int v) { 108 | int V = distTo.length; 109 | if (v < 0 || v >= V) 110 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 111 | } 112 | 113 | public static void main(String[] args) { 114 | In in = new In(args[0]); 115 | EdgeWeightedDigraph G = new EdgeWeightedDigraph(in); 116 | int s = Integer.parseInt(args[1]); 117 | 118 | DijkstraSP sp = new DijkstraSP(G, s); 119 | 120 | 121 | for (int t = 0; t < G.V(); t++) { 122 | if (sp.hasPathTo(t)) { 123 | StdOut.printf("%d to %d (%.2f) ", s, t, sp.distTo(t)); 124 | for (DirectedEdge e : sp.pathTo(t)) { 125 | StdOut.print(e + " "); 126 | } 127 | StdOut.println(); 128 | } 129 | else { 130 | StdOut.printf("%d to %d no path\n", s, t); 131 | } 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /Chapter 5 字符串 Strings/5.6 substring search (Knuth–Morris–Pratt).java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code KMP} class finds the first occurrence of a pattern string 3 | * in a text string. 4 | * This implementation uses a version of the Knuth-Morris-Pratt substring search 5 | * algorithm. The version takes time as space proportional to 6 | * N + M R in the worst case, where N is the length 7 | * of the text string, M is the length of the pattern, and R 8 | * is the alphabet size. 9 | */ 10 | public class KMP { 11 | private final int R; // the radix 12 | private int[][] dfa; // the KMP automoton 13 | 14 | private char[] pattern; // either the character array for the pattern 15 | private String pat; // or the pattern string 16 | 17 | /** 18 | * Preprocesses the pattern string. 19 | * 20 | * @param pat the pattern string 21 | */ 22 | public KMP(String pat) { 23 | this.R = 256; 24 | this.pat = pat; 25 | 26 | // build DFA from pattern 27 | int m = pat.length(); 28 | dfa = new int[R][m]; 29 | dfa[pat.charAt(0)][0] = 1; 30 | for (int x = 0, j = 1; j < m; j++) { 31 | for (int c = 0; c < R; c++) 32 | dfa[c][j] = dfa[c][x]; // Copy mismatch cases. 33 | dfa[pat.charAt(j)][j] = j+1; // Set match case. 34 | x = dfa[pat.charAt(j)][x]; // Update restart state. 35 | } 36 | } 37 | 38 | /** 39 | * Preprocesses the pattern string. 40 | * 41 | * @param pattern the pattern string 42 | * @param R the alphabet size 43 | */ 44 | public KMP(char[] pattern, int R) { 45 | this.R = R; 46 | this.pattern = new char[pattern.length]; 47 | for (int j = 0; j < pattern.length; j++) 48 | this.pattern[j] = pattern[j]; 49 | 50 | // build DFA from pattern 51 | int m = pattern.length; 52 | dfa = new int[R][m]; 53 | dfa[pattern[0]][0] = 1; 54 | for (int x = 0, j = 1; j < m; j++) { 55 | for (int c = 0; c < R; c++) 56 | dfa[c][j] = dfa[c][x]; // Copy mismatch cases. 57 | dfa[pattern[j]][j] = j+1; // Set match case. 58 | x = dfa[pattern[j]][x]; // Update restart state. 59 | } 60 | } 61 | 62 | /** 63 | * Returns the index of the first occurrrence of the pattern string 64 | * in the text string. 65 | * 66 | * @param txt the text string 67 | * @return the index of the first occurrence of the pattern string 68 | * in the text string; N if no such match 69 | */ 70 | public int search(String txt) { 71 | 72 | // simulate operation of DFA on text 73 | int m = pat.length(); 74 | int n = txt.length(); 75 | int i, j; 76 | for (i = 0, j = 0; i < n && j < m; i++) { 77 | j = dfa[txt.charAt(i)][j]; 78 | } 79 | if (j == m) return i - m; // found 80 | return n; // not found 81 | } 82 | 83 | /** 84 | * Returns the index of the first occurrrence of the pattern string 85 | * in the text string. 86 | * 87 | * @param text the text string 88 | * @return the index of the first occurrence of the pattern string 89 | * in the text string; N if no such match 90 | */ 91 | public int search(char[] text) { 92 | 93 | // simulate operation of DFA on text 94 | int m = pattern.length; 95 | int n = text.length; 96 | int i, j; 97 | for (i = 0, j = 0; i < n && j < m; i++) { 98 | j = dfa[text[i]][j]; 99 | } 100 | if (j == m) return i - m; // found 101 | return n; // not found 102 | } 103 | 104 | 105 | /** 106 | * Takes a pattern string and an input string as command-line arguments; 107 | * searches for the pattern string in the text string; and prints 108 | * the first occurrence of the pattern string in the text string. 109 | * 110 | * @param args the command-line arguments 111 | */ 112 | public static void main(String[] args) { 113 | String pat = args[0]; 114 | String txt = args[1]; 115 | char[] pattern = pat.toCharArray(); 116 | char[] text = txt.toCharArray(); 117 | 118 | KMP kmp1 = new KMP(pat); 119 | int offset1 = kmp1.search(txt); 120 | 121 | KMP kmp2 = new KMP(pattern, 256); 122 | int offset2 = kmp2.search(text); 123 | 124 | // print results 125 | StdOut.println("text: " + txt); 126 | 127 | StdOut.print("pattern: "); 128 | for (int i = 0; i < offset1; i++) 129 | StdOut.print(" "); 130 | StdOut.println(pat); 131 | 132 | StdOut.print("pattern: "); 133 | for (int i = 0; i < offset2; i++) 134 | StdOut.print(" "); 135 | StdOut.println(pat); 136 | } 137 | } -------------------------------------------------------------------------------- /Chapter 4 图 Graph/4.5 topological order in a DAG.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * The {@code Topological} class represents a data type for 4 | * determining a topological order of a directed acyclic graph (DAG). 5 | * Recall, a digraph has a topological order if and only if it is a DAG. 6 | * The hasOrder operation determines whether the digraph has 7 | * a topological order, and if so, the order operation 8 | * returns one. 9 | * This implementation uses depth-first search. 10 | * The constructor takes time proportional to V + E 11 | * (in the worst case), 12 | * where V is the number of vertices and E is the number of edges. 13 | * Afterwards, the hasOrder and rank operations takes constant time; 14 | * the order operation takes time proportional to V. 15 | * See {@link DirectedCycle}, {@link DirectedCycleX}, and 16 | * {@link EdgeWeightedDirectedCycle} to compute a 17 | * directed cycle if the digraph is not a DAG. 18 | * See {@link TopologicalX} for a nonrecursive queue-based algorithm 19 | * to compute a topological order of a DAG. 20 | * @author Robert Sedgewick 21 | * @author Kevin Wayne 22 | */ 23 | public class Topological { 24 | private Iterable order; // topological order 25 | private int[] rank; // rank[v] = position of vertex v in topological order 26 | 27 | /** 28 | * Determines whether the digraph {@code G} has a topological order and, if so, 29 | * finds such a topological order. 30 | * @param G the digraph 31 | */ 32 | public Topological(Digraph G) { 33 | DirectedCycle finder = new DirectedCycle(G); 34 | if (!finder.hasCycle()) { 35 | DepthFirstOrder dfs = new DepthFirstOrder(G); 36 | order = dfs.reversePost(); 37 | rank = new int[G.V()]; 38 | int i = 0; 39 | for (int v : order) 40 | rank[v] = i++; 41 | } 42 | } 43 | 44 | /** 45 | * Determines whether the edge-weighted digraph {@code G} has a topological 46 | * order and, if so, finds such an order. 47 | * @param G the edge-weighted digraph 48 | */ 49 | public Topological(EdgeWeightedDigraph G) { 50 | EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(G); 51 | if (!finder.hasCycle()) { 52 | DepthFirstOrder dfs = new DepthFirstOrder(G); 53 | order = dfs.reversePost(); 54 | } 55 | } 56 | 57 | /** 58 | * Returns a topological order if the digraph has a topologial order, 59 | * and {@code null} otherwise. 60 | * @return a topological order of the vertices (as an interable) if the 61 | * digraph has a topological order (or equivalently, if the digraph is a DAG), 62 | * and {@code null} otherwise 63 | */ 64 | public Iterable order() { 65 | return order; 66 | } 67 | 68 | /** 69 | * Does the digraph have a topological order? 70 | * @return {@code true} if the digraph has a topological order (or equivalently, 71 | * if the digraph is a DAG), and {@code false} otherwise 72 | */ 73 | public boolean hasOrder() { 74 | return order != null; 75 | } 76 | 77 | /** 78 | * Does the digraph have a topological order? 79 | * @return {@code true} if the digraph has a topological order (or equivalently, 80 | * if the digraph is a DAG), and {@code false} otherwise 81 | * @deprecated Replaced by {@link #hasOrder()}. 82 | */ 83 | @Deprecated 84 | public boolean isDAG() { 85 | return hasOrder(); 86 | } 87 | 88 | /** 89 | * The the rank of vertex {@code v} in the topological order; 90 | * -1 if the digraph is not a DAG 91 | * 92 | * @param v the vertex 93 | * @return the position of vertex {@code v} in a topological order 94 | * of the digraph; -1 if the digraph is not a DAG 95 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 96 | */ 97 | public int rank(int v) { 98 | validateVertex(v); 99 | if (hasOrder()) return rank[v]; 100 | else return -1; 101 | } 102 | 103 | // throw an IllegalArgumentException unless {@code 0 <= v < V} 104 | private void validateVertex(int v) { 105 | int V = rank.length; 106 | if (v < 0 || v >= V) 107 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 108 | } 109 | 110 | /** 111 | * Unit tests the {@code Topological} data type. 112 | * 113 | * @param args the command-line arguments 114 | */ 115 | public static void main(String[] args) { 116 | String filename = args[0]; 117 | String delimiter = args[1]; 118 | SymbolDigraph sg = new SymbolDigraph(filename, delimiter); 119 | Topological topological = new Topological(sg.digraph()); 120 | for (int v : topological.order()) { 121 | StdOut.println(sg.nameOf(v)); 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /Chapter 5 字符串 Strings/5.9 NFA for regular expressions.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code NFA} class provides a data type for creating a 3 | * nondeterministic finite state automaton (NFA) from a regular 4 | * expression and testing whether a given string is matched by that regular 5 | * expression. 6 | * It supports the following operations: concatenation, 7 | * closure, binary or, and parentheses. 8 | * It does not support mutiway or, character classes, 9 | * metacharacters (either in the text or pattern), 10 | * capturing capabilities, greedy or relucantant 11 | * modifiers, and other features in industrial-strength implementations 12 | * such as {@link java.util.regex.Pattern} and {@link java.util.regex.Matcher}. 13 | * This implementation builds the NFA using a digraph and a stack 14 | * and simulates the NFA using digraph search (see the textbook for details). 15 | * The constructor takes time proportional to m, where m 16 | * is the number of characters in the regular expression. 17 | * The recognizes method takes time proportional to m n, 18 | * where n is the number of characters in the text. 19 | * @author Robert Sedgewick 20 | * @author Kevin Wayne 21 | */ 22 | public class NFA { 23 | 24 | private Digraph graph; // digraph of epsilon transitions 25 | private String regexp; // regular expression 26 | private final int m; // number of characters in regular expression 27 | 28 | /** 29 | * Initializes the NFA from the specified regular expression. 30 | * 31 | * @param regexp the regular expression 32 | */ 33 | public NFA(String regexp) { 34 | this.regexp = regexp; 35 | m = regexp.length(); 36 | Stack ops = new Stack(); 37 | graph = new Digraph(m+1); 38 | for (int i = 0; i < m; i++) { 39 | int lp = i; 40 | if (regexp.charAt(i) == '(' || regexp.charAt(i) == '|') 41 | ops.push(i); 42 | else if (regexp.charAt(i) == ')') { 43 | int or = ops.pop(); 44 | 45 | // 2-way or operator 46 | if (regexp.charAt(or) == '|') { 47 | lp = ops.pop(); 48 | graph.addEdge(lp, or+1); 49 | graph.addEdge(or, i); 50 | } 51 | else if (regexp.charAt(or) == '(') 52 | lp = or; 53 | else assert false; 54 | } 55 | 56 | // closure operator (uses 1-character lookahead) 57 | if (i < m-1 && regexp.charAt(i+1) == '*') { 58 | graph.addEdge(lp, i+1); 59 | graph.addEdge(i+1, lp); 60 | } 61 | if (regexp.charAt(i) == '(' || regexp.charAt(i) == '*' || regexp.charAt(i) == ')') 62 | graph.addEdge(i, i+1); 63 | } 64 | if (ops.size() != 0) 65 | throw new IllegalArgumentException("Invalid regular expression"); 66 | } 67 | 68 | /** 69 | * Returns true if the text is matched by the regular expression. 70 | * 71 | * @param txt the text 72 | * @return {@code true} if the text is matched by the regular expression, 73 | * {@code false} otherwise 74 | */ 75 | public boolean recognizes(String txt) { 76 | DirectedDFS dfs = new DirectedDFS(graph, 0); 77 | Bag pc = new Bag(); 78 | for (int v = 0; v < graph.V(); v++) 79 | if (dfs.marked(v)) pc.add(v); 80 | 81 | // Compute possible NFA states for txt[i+1] 82 | for (int i = 0; i < txt.length(); i++) { 83 | if (txt.charAt(i) == '*' || txt.charAt(i) == '|' || txt.charAt(i) == '(' || txt.charAt(i) == ')') 84 | throw new IllegalArgumentException("text contains the metacharacter '" + txt.charAt(i) + "'"); 85 | 86 | Bag match = new Bag(); 87 | for (int v : pc) { 88 | if (v == m) continue; 89 | if ((regexp.charAt(v) == txt.charAt(i)) || regexp.charAt(v) == '.') 90 | match.add(v+1); 91 | } 92 | dfs = new DirectedDFS(graph, match); 93 | pc = new Bag(); 94 | for (int v = 0; v < graph.V(); v++) 95 | if (dfs.marked(v)) pc.add(v); 96 | 97 | // optimization if no states reachable 98 | if (pc.size() == 0) return false; 99 | } 100 | 101 | // check for accept state 102 | for (int v : pc) 103 | if (v == m) return true; 104 | return false; 105 | } 106 | 107 | /** 108 | * Unit tests the {@code NFA} data type. 109 | * 110 | * @param args the command-line arguments 111 | */ 112 | public static void main(String[] args) { 113 | String regexp = "(" + args[0] + ")"; 114 | String txt = args[1]; 115 | NFA nfa = new NFA(regexp); 116 | StdOut.println(nfa.recognizes(txt)); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-6.1 collision system.java: -------------------------------------------------------------------------------- 1 | import java.awt.Color; 2 | 3 | public class CollisionSystem { 4 | private final static double HZ = 0.5; 5 | 6 | private MinPQ pq; 7 | private double t = 0.0; 8 | private Particle[] particles; 9 | 10 | public CollisionSystem(Particle[] particles) { 11 | this.particles = particles.clone(); 12 | } 13 | 14 | private void predict(Particle a, double limit) { 15 | if (a == null) return; 16 | 17 | for (int i = 0; i < particles.length; i++) { 18 | double dt = a.timeToHit(particles[i]); 19 | if (t + dt <= limit) 20 | pq.insert(new Event(t + dt, a, particles[i])); 21 | } 22 | 23 | double dtX = a.timeToHitVerticalWall(); 24 | double dtY = a.timeToHitHorizontalWall(); 25 | if (t + dtX <= limit) pq.insert(new Event(t + dtX, a, null)); 26 | if (t + dtY <= limit) pq.insert(new Event(t + dtY, null, a)); 27 | } 28 | 29 | private void redraw(double limit) { 30 | StdDraw.clear(); 31 | for (int i = 0; i < particles.length; i++) { 32 | particles[i].draw(); 33 | } 34 | StdDraw.show(); 35 | StdDraw.pause(20); 36 | if (t < limit) { 37 | pq.insert(new Event(t + 1.0 / HZ, null, null)); 38 | } 39 | } 40 | 41 | 42 | public void simulate(double limit) { 43 | 44 | pq = new MinPQ(); 45 | for (int i = 0; i < particles.length; i++) { 46 | predict(particles[i], limit); 47 | } 48 | pq.insert(new Event(0, null, null)); 49 | 50 | 51 | while (!pq.isEmpty()) { 52 | 53 | Event e = pq.delMin(); 54 | if (!e.isValid()) continue; 55 | Particle a = e.a; 56 | Particle b = e.b; 57 | 58 | for (int i = 0; i < particles.length; i++) 59 | particles[i].move(e.time - t); 60 | t = e.time; 61 | 62 | if (a != null && b != null) a.bounceOff(b); 63 | else if (a != null && b == null) a.bounceOffVerticalWall(); 64 | else if (a == null && b != null) b.bounceOffHorizontalWall(); 65 | else if (a == null && b == null) redraw(limit); 66 | 67 | predict(a, limit); 68 | predict(b, limit); 69 | } 70 | } 71 | 72 | 73 | private static class Event implements Comparable { 74 | private final double time; 75 | private final Particle a, b; 76 | private final int countA, countB; 77 | 78 | 79 | public Event(double t, Particle a, Particle b) { 80 | this.time = t; 81 | this.a = a; 82 | this.b = b; 83 | if (a != null) countA = a.count(); 84 | else countA = -1; 85 | if (b != null) countB = b.count(); 86 | else countB = -1; 87 | } 88 | 89 | public int compareTo(Event that) { 90 | return Double.compare(this.time, that.time); 91 | } 92 | 93 | public boolean isValid() { 94 | if (a != null && a.count() != countA) return false; 95 | if (b != null && b.count() != countB) return false; 96 | return true; 97 | } 98 | 99 | } 100 | 101 | 102 | public static void main(String[] args) { 103 | 104 | StdDraw.setCanvasSize(800, 800); 105 | 106 | 107 | StdDraw.enableDoubleBuffering(); 108 | 109 | Particle[] particles; 110 | 111 | if (args.length == 1) { 112 | int n = Integer.parseInt(args[0]); 113 | particles = new Particle[n]; 114 | for (int i = 0; i < n; i++) 115 | particles[i] = new Particle(); 116 | } 117 | 118 | else { 119 | int n = StdIn.readInt(); 120 | particles = new Particle[n]; 121 | for (int i = 0; i < n; i++) { 122 | double rx = StdIn.readDouble(); 123 | double ry = StdIn.readDouble(); 124 | double vx = StdIn.readDouble(); 125 | double vy = StdIn.readDouble(); 126 | double radius = StdIn.readDouble(); 127 | double mass = StdIn.readDouble(); 128 | int r = StdIn.readInt(); 129 | int g = StdIn.readInt(); 130 | int b = StdIn.readInt(); 131 | Color color = new Color(r, g, b); 132 | particles[i] = new Particle(rx, ry, vx, vy, radius, mass, color); 133 | } 134 | } 135 | 136 | CollisionSystem system = new CollisionSystem(particles); 137 | system.simulate(10000); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /chapter 1 基础 Fundamental/1.1 LIFO stack (resizing array).java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.NoSuchElementException; 3 | /** 4 | * The {@code ResizingArrayStack} class represents a last-in-first-out (LIFO) stack 5 | * of generic items. 6 | * It supports the usual push and pop operations, along with methods 7 | * for peeking at the top item, testing if the stack is empty, and iterating through 8 | * the items in LIFO order. 9 | * This implementation uses a resizing array, which double the underlying array 10 | * when it is full and halves the underlying array when it is one-quarter full. 11 | * The push and pop operations take constant amortized time. 12 | * The size, peek, and is-empty operations takes 13 | * constant time in the worst case. 14 | * @author Robert Sedgewick 15 | * @author Kevin Wayne 16 | */ 17 | public class ResizingArrayStack implements Iterable { 18 | private Item[] a; // array of items 19 | private int n; // number of elements on stack 20 | 21 | 22 | /** 23 | * Initializes an empty stack. 24 | */ 25 | public ResizingArrayStack() { 26 | a = (Item[]) new Object[2]; 27 | n = 0; 28 | } 29 | 30 | /** 31 | * Is this stack empty? 32 | * @return true if this stack is empty; false otherwise 33 | */ 34 | public boolean isEmpty() { 35 | return n == 0; 36 | } 37 | 38 | /** 39 | * Returns the number of items in the stack. 40 | * @return the number of items in the stack 41 | */ 42 | public int size() { 43 | return n; 44 | } 45 | 46 | 47 | // resize the underlying array holding the elements 48 | private void resize(int capacity) { 49 | assert capacity >= n; 50 | 51 | // textbook implementation 52 | Item[] temp = (Item[]) new Object[capacity]; 53 | for (int i = 0; i < n; i++) { 54 | temp[i] = a[i]; 55 | } 56 | a = temp; 57 | 58 | // alternative implementation 59 | // a = java.util.Arrays.copyOf(a, capacity); 60 | } 61 | 62 | 63 | 64 | /** 65 | * Adds the item to this stack. 66 | * @param item the item to add 67 | */ 68 | public void push(Item item) { 69 | if (n == a.length) resize(2*a.length); // double size of array if necessary 70 | a[n++] = item; // add item 71 | } 72 | 73 | /** 74 | * Removes and returns the item most recently added to this stack. 75 | * @return the item most recently added 76 | * @throws java.util.NoSuchElementException if this stack is empty 77 | */ 78 | public Item pop() { 79 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 80 | Item item = a[n-1]; 81 | a[n-1] = null; // to avoid loitering 82 | n--; 83 | // shrink size of array if necessary 84 | if (n > 0 && n == a.length/4) resize(a.length/2); 85 | return item; 86 | } 87 | 88 | 89 | /** 90 | * Returns (but does not remove) the item most recently added to this stack. 91 | * @return the item most recently added to this stack 92 | * @throws java.util.NoSuchElementException if this stack is empty 93 | */ 94 | public Item peek() { 95 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 96 | return a[n-1]; 97 | } 98 | 99 | /** 100 | * Returns an iterator to this stack that iterates through the items in LIFO order. 101 | * @return an iterator to this stack that iterates through the items in LIFO order. 102 | */ 103 | public Iterator iterator() { 104 | return new ReverseArrayIterator(); 105 | } 106 | 107 | // an iterator, doesn't implement remove() since it's optional 108 | private class ReverseArrayIterator implements Iterator { 109 | private int i; 110 | 111 | public ReverseArrayIterator() { 112 | i = n-1; 113 | } 114 | 115 | public boolean hasNext() { 116 | return i >= 0; 117 | } 118 | 119 | public void remove() { 120 | throw new UnsupportedOperationException(); 121 | } 122 | 123 | public Item next() { 124 | if (!hasNext()) throw new NoSuchElementException(); 125 | return a[i--]; 126 | } 127 | } 128 | 129 | 130 | /** 131 | * Unit tests the {@code Stack} data type. 132 | * 133 | * @param args the command-line arguments 134 | */ 135 | public static void main(String[] args) { 136 | ResizingArrayStack stack = new ResizingArrayStack(); 137 | while (!StdIn.isEmpty()) { 138 | String item = StdIn.readString(); 139 | if (!item.equals("-")) stack.push(item); 140 | else if (!stack.isEmpty()) StdOut.print(stack.pop() + " "); 141 | } 142 | StdOut.println("(" + stack.size() + " left on stack)"); 143 | } 144 | } 145 | 146 | 147 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-2.6 max heap priority queue.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | import java.util.Iterator; 3 | import java.util.NoSuchElementException; 4 | 5 | 6 | public class MaxPQ implements Iterable { 7 | private Key[] pq; 8 | private int n; 9 | private Comparator comparator; 10 | 11 | public MaxPQ(int initCapacity) { 12 | pq = (Key[]) new Object[initCapacity + 1]; 13 | n = 0; 14 | } 15 | 16 | public MaxPQ() { 17 | this(1); 18 | } 19 | 20 | public MaxPQ(int initCapacity, Comparator comparator) { 21 | this.comparator = comparator; 22 | pq = (Key[]) new Object[initCapacity + 1]; 23 | n = 0; 24 | } 25 | 26 | public MaxPQ(Comparator comparator) { 27 | this(1, comparator); 28 | } 29 | 30 | public MaxPQ(Key[] keys) { 31 | n = keys.length; 32 | pq = (Key[]) new Object[keys.length + 1]; 33 | for (int i = 0; i < n; i++) 34 | pq[i+1] = keys[i]; 35 | for (int k = n/2; k >= 1; k--) 36 | sink(k); 37 | assert isMaxHeap(); 38 | } 39 | 40 | 41 | 42 | public boolean isEmpty() { 43 | return n == 0; 44 | } 45 | 46 | public int size() { 47 | return n; 48 | } 49 | 50 | public Key max() { 51 | if (isEmpty()) throw new NoSuchElementException("Priority queue underflow"); 52 | return pq[1]; 53 | } 54 | 55 | private void resize(int capacity) { 56 | assert capacity > n; 57 | Key[] temp = (Key[]) new Object[capacity]; 58 | for (int i = 1; i <= n; i++) { 59 | temp[i] = pq[i]; 60 | } 61 | pq = temp; 62 | } 63 | 64 | 65 | public void insert(Key x) { 66 | 67 | if (n == pq.length - 1) resize(2 * pq.length); 68 | 69 | pq[++n] = x; 70 | swim(n); 71 | assert isMaxHeap(); 72 | } 73 | 74 | public Key delMax() { 75 | if (isEmpty()) throw new NoSuchElementException("Priority queue underflow"); 76 | Key max = pq[1]; 77 | exch(1, n--); 78 | sink(1); 79 | pq[n+1] = null; 80 | if ((n > 0) && (n == (pq.length - 1) / 4)) resize(pq.length / 2); 81 | assert isMaxHeap(); 82 | return max; 83 | } 84 | 85 | 86 | 87 | private void swim(int k) { 88 | while (k > 1 && less(k/2, k)) { 89 | exch(k, k/2); 90 | k = k/2; 91 | } 92 | } 93 | 94 | private void sink(int k) { 95 | while (2*k <= n) { 96 | int j = 2*k; 97 | if (j < n && less(j, j+1)) j++; 98 | if (!less(k, j)) break; 99 | exch(k, j); 100 | k = j; 101 | } 102 | } 103 | 104 | private boolean less(int i, int j) { 105 | if (comparator == null) { 106 | return ((Comparable) pq[i]).compareTo(pq[j]) < 0; 107 | } 108 | else { 109 | return comparator.compare(pq[i], pq[j]) < 0; 110 | } 111 | } 112 | 113 | private void exch(int i, int j) { 114 | Key swap = pq[i]; 115 | pq[i] = pq[j]; 116 | pq[j] = swap; 117 | } 118 | 119 | private boolean isMaxHeap() { 120 | return isMaxHeap(1); 121 | } 122 | 123 | private boolean isMaxHeap(int k) { 124 | if (k > n) return true; 125 | int left = 2*k; 126 | int right = 2*k + 1; 127 | if (left <= n && less(k, left)) return false; 128 | if (right <= n && less(k, right)) return false; 129 | return isMaxHeap(left) && isMaxHeap(right); 130 | } 131 | 132 | 133 | 134 | public Iterator iterator() { 135 | return new HeapIterator(); 136 | } 137 | 138 | private class HeapIterator implements Iterator { 139 | 140 | private MaxPQ copy; 141 | 142 | public HeapIterator() { 143 | if (comparator == null) copy = new MaxPQ(size()); 144 | else copy = new MaxPQ(size(), comparator); 145 | for (int i = 1; i <= n; i++) 146 | copy.insert(pq[i]); 147 | } 148 | 149 | public boolean hasNext() { return !copy.isEmpty(); } 150 | public void remove() { throw new UnsupportedOperationException(); } 151 | 152 | public Key next() { 153 | if (!hasNext()) throw new NoSuchElementException(); 154 | return copy.delMax(); 155 | } 156 | } 157 | 158 | public static void main(String[] args) { 159 | MaxPQ pq = new MaxPQ(); 160 | while (!StdIn.isEmpty()) { 161 | String item = StdIn.readString(); 162 | if (!item.equals("-")) pq.insert(item); 163 | else if (!pq.isEmpty()) StdOut.print(pq.delMax() + " "); 164 | } 165 | StdOut.println("(" + pq.size() + " left on pq)"); 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /Chapter 2 排序 Sorting/2.5 quicksort.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code Quick} class provides static methods for sorting an 3 | * array and selecting the ith smallest element in an array using quicksort. 4 | * @author Robert Sedgewick 5 | * @author Kevin Wayne 6 | */ 7 | public class Quick { 8 | 9 | // This class should not be instantiated. 10 | private Quick() { } 11 | 12 | /** 13 | * Rearranges the array in ascending order, using the natural order. 14 | * @param a the array to be sorted 15 | */ 16 | public static void sort(Comparable[] a) { 17 | StdRandom.shuffle(a); 18 | sort(a, 0, a.length - 1); 19 | assert isSorted(a); 20 | } 21 | 22 | // quicksort the subarray from a[lo] to a[hi] 23 | private static void sort(Comparable[] a, int lo, int hi) { 24 | if (hi <= lo) return; 25 | int j = partition(a, lo, hi); 26 | sort(a, lo, j-1); 27 | sort(a, j+1, hi); 28 | assert isSorted(a, lo, hi); 29 | } 30 | 31 | // partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi] 32 | // and return the index j. 33 | private static int partition(Comparable[] a, int lo, int hi) { 34 | int i = lo; 35 | int j = hi + 1; 36 | Comparable v = a[lo]; 37 | while (true) { 38 | 39 | // find item on lo to swap 40 | while (less(a[++i], v)) 41 | if (i == hi) break; 42 | 43 | // find item on hi to swap 44 | while (less(v, a[--j])) 45 | if (j == lo) break; // redundant since a[lo] acts as sentinel 46 | 47 | // check if pointers cross 48 | if (i >= j) break; 49 | 50 | exch(a, i, j); 51 | } 52 | 53 | // put partitioning item v at a[j] 54 | exch(a, lo, j); 55 | 56 | // now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi] 57 | return j; 58 | } 59 | 60 | /** 61 | * Rearranges the array so that {@code a[k]} contains the kth smallest key; 62 | * {@code a[0]} through {@code a[k-1]} are less than (or equal to) {@code a[k]}; and 63 | * {@code a[k+1]} through {@code a[n-1]} are greater than (or equal to) {@code a[k]}. 64 | * 65 | * @param a the array 66 | * @param k the rank of the key 67 | * @return the key of rank {@code k} 68 | */ 69 | public static Comparable select(Comparable[] a, int k) { 70 | if (k < 0 || k >= a.length) { 71 | throw new IndexOutOfBoundsException("Selected element out of bounds"); 72 | } 73 | StdRandom.shuffle(a); 74 | int lo = 0, hi = a.length - 1; 75 | while (hi > lo) { 76 | int i = partition(a, lo, hi); 77 | if (i > k) hi = i - 1; 78 | else if (i < k) lo = i + 1; 79 | else return a[i]; 80 | } 81 | return a[lo]; 82 | } 83 | 84 | 85 | 86 | /*************************************************************************** 87 | * Helper sorting functions. 88 | ***************************************************************************/ 89 | 90 | // is v < w ? 91 | private static boolean less(Comparable v, Comparable w) { 92 | return v.compareTo(w) < 0; 93 | } 94 | 95 | // exchange a[i] and a[j] 96 | private static void exch(Object[] a, int i, int j) { 97 | Object swap = a[i]; 98 | a[i] = a[j]; 99 | a[j] = swap; 100 | } 101 | 102 | 103 | /*************************************************************************** 104 | * Check if array is sorted - useful for debugging. 105 | ***************************************************************************/ 106 | private static boolean isSorted(Comparable[] a) { 107 | return isSorted(a, 0, a.length - 1); 108 | } 109 | 110 | private static boolean isSorted(Comparable[] a, int lo, int hi) { 111 | for (int i = lo + 1; i <= hi; i++) 112 | if (less(a[i], a[i-1])) return false; 113 | return true; 114 | } 115 | 116 | 117 | // print array to standard output 118 | private static void show(Comparable[] a) { 119 | for (int i = 0; i < a.length; i++) { 120 | StdOut.println(a[i]); 121 | } 122 | } 123 | 124 | /** 125 | * Reads in a sequence of strings from standard input; quicksorts them; 126 | * and prints them to standard output in ascending order. 127 | * Shuffles the array and then prints the strings again to 128 | * standard output, but this time, using the select method. 129 | * 130 | * @param args the command-line arguments 131 | */ 132 | public static void main(String[] args) { 133 | String[] a = StdIn.readAllStrings(); 134 | Quick.sort(a); 135 | show(a); 136 | assert isSorted(a); 137 | 138 | // shuffle 139 | StdRandom.shuffle(a); 140 | 141 | // display results again using select 142 | StdOut.println(); 143 | for (int i = 0; i < a.length; i++) { 144 | String ith = (String) Quick.select(a, i); 145 | StdOut.println(ith); 146 | } 147 | } 148 | 149 | } -------------------------------------------------------------------------------- /Chapter 4 图 Graph/4.10 shortest paths in a DAG.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code AcyclicSP} class represents a data type for solving the 3 | * single-source shortest paths problem in edge-weighted directed acyclic 4 | * graphs (DAGs). The edge weights can be positive, negative, or zero. 5 | * This implementation uses a topological-sort based algorithm. 6 | * The constructor takes time proportional to V + E, 7 | * where V is the number of vertices and E is the number of edges. 8 | * Afterwards, the {@code distTo()} and {@code hasPathTo()} methods take 9 | * constant time and the {@code pathTo()} method takes time proportional to the 10 | * number of edges in the shortest path returned. 11 | * @author Robert Sedgewick 12 | * @author Kevin Wayne 13 | */ 14 | public class AcyclicSP { 15 | private double[] distTo; // distTo[v] = distance of shortest s->v path 16 | private DirectedEdge[] edgeTo; // edgeTo[v] = last edge on shortest s->v path 17 | 18 | 19 | /** 20 | * Computes a shortest paths tree from {@code s} to every other vertex in 21 | * the directed acyclic graph {@code G}. 22 | * @param G the acyclic digraph 23 | * @param s the source vertex 24 | * @throws IllegalArgumentException if the digraph is not acyclic 25 | * @throws IllegalArgumentException unless {@code 0 <= s < V} 26 | */ 27 | public AcyclicSP(EdgeWeightedDigraph G, int s) { 28 | distTo = new double[G.V()]; 29 | edgeTo = new DirectedEdge[G.V()]; 30 | 31 | validateVertex(s); 32 | 33 | for (int v = 0; v < G.V(); v++) 34 | distTo[v] = Double.POSITIVE_INFINITY; 35 | distTo[s] = 0.0; 36 | 37 | // visit vertices in toplogical order 38 | Topological topological = new Topological(G); 39 | if (!topological.hasOrder()) 40 | throw new IllegalArgumentException("Digraph is not acyclic."); 41 | for (int v : topological.order()) { 42 | for (DirectedEdge e : G.adj(v)) 43 | relax(e); 44 | } 45 | } 46 | 47 | // relax edge e 48 | private void relax(DirectedEdge e) { 49 | int v = e.from(), w = e.to(); 50 | if (distTo[w] > distTo[v] + e.weight()) { 51 | distTo[w] = distTo[v] + e.weight(); 52 | edgeTo[w] = e; 53 | } 54 | } 55 | 56 | /** 57 | * Returns the length of a shortest path from the source vertex {@code s} to vertex {@code v}. 58 | * @param v the destination vertex 59 | * @return the length of a shortest path from the source vertex {@code s} to vertex {@code v}; 60 | * {@code Double.POSITIVE_INFINITY} if no such path 61 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 62 | */ 63 | public double distTo(int v) { 64 | validateVertex(v); 65 | return distTo[v]; 66 | } 67 | 68 | /** 69 | * Is there a path from the source vertex {@code s} to vertex {@code v}? 70 | * @param v the destination vertex 71 | * @return {@code true} if there is a path from the source vertex 72 | * {@code s} to vertex {@code v}, and {@code false} otherwise 73 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 74 | */ 75 | public boolean hasPathTo(int v) { 76 | validateVertex(v); 77 | return distTo[v] < Double.POSITIVE_INFINITY; 78 | } 79 | 80 | /** 81 | * Returns a shortest path from the source vertex {@code s} to vertex {@code v}. 82 | * @param v the destination vertex 83 | * @return a shortest path from the source vertex {@code s} to vertex {@code v} 84 | * as an iterable of edges, and {@code null} if no such path 85 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 86 | */ 87 | public Iterable pathTo(int v) { 88 | validateVertex(v); 89 | if (!hasPathTo(v)) return null; 90 | Stack path = new Stack(); 91 | for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) { 92 | path.push(e); 93 | } 94 | return path; 95 | } 96 | 97 | // throw an IllegalArgumentException unless {@code 0 <= v < V} 98 | private void validateVertex(int v) { 99 | int V = distTo.length; 100 | if (v < 0 || v >= V) 101 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 102 | } 103 | 104 | /** 105 | * Unit tests the {@code AcyclicSP} data type. 106 | * 107 | * @param args the command-line arguments 108 | */ 109 | public static void main(String[] args) { 110 | In in = new In(args[0]); 111 | int s = Integer.parseInt(args[1]); 112 | EdgeWeightedDigraph G = new EdgeWeightedDigraph(in); 113 | 114 | // find shortest path from s to each other vertex in DAG 115 | AcyclicSP sp = new AcyclicSP(G, s); 116 | for (int v = 0; v < G.V(); v++) { 117 | if (sp.hasPathTo(v)) { 118 | StdOut.printf("%d to %d (%.2f) ", s, v, sp.distTo(v)); 119 | for (DirectedEdge e : sp.pathTo(v)) { 120 | StdOut.print(e + " "); 121 | } 122 | StdOut.println(); 123 | } 124 | else { 125 | StdOut.printf("%d to %d no path\n", s, v); 126 | } 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /Chapter 2 排序 Sorting/2.4 top-down mergesort.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code Merge} class provides static methods for sorting an 3 | * array using mergesort. 4 | * @author Robert Sedgewick 5 | * @author Kevin Wayne 6 | */ 7 | public class Merge { 8 | 9 | // This class should not be instantiated. 10 | private Merge() { } 11 | 12 | // stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi] 13 | private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) { 14 | // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays 15 | assert isSorted(a, lo, mid); 16 | assert isSorted(a, mid+1, hi); 17 | 18 | // copy to aux[] 19 | for (int k = lo; k <= hi; k++) { 20 | aux[k] = a[k]; 21 | } 22 | 23 | // merge back to a[] 24 | int i = lo, j = mid+1; 25 | for (int k = lo; k <= hi; k++) { 26 | if (i > mid) a[k] = aux[j++]; 27 | else if (j > hi) a[k] = aux[i++]; 28 | else if (less(aux[j], aux[i])) a[k] = aux[j++]; 29 | else a[k] = aux[i++]; 30 | } 31 | 32 | // postcondition: a[lo .. hi] is sorted 33 | assert isSorted(a, lo, hi); 34 | } 35 | 36 | // mergesort a[lo..hi] using auxiliary array aux[lo..hi] 37 | private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) { 38 | if (hi <= lo) return; 39 | int mid = lo + (hi - lo) / 2; 40 | sort(a, aux, lo, mid); 41 | sort(a, aux, mid + 1, hi); 42 | merge(a, aux, lo, mid, hi); 43 | } 44 | 45 | /** 46 | * Rearranges the array in ascending order, using the natural order. 47 | * @param a the array to be sorted 48 | */ 49 | public static void sort(Comparable[] a) { 50 | Comparable[] aux = new Comparable[a.length]; 51 | sort(a, aux, 0, a.length-1); 52 | assert isSorted(a); 53 | } 54 | 55 | 56 | /*************************************************************************** 57 | * Helper sorting function. 58 | ***************************************************************************/ 59 | 60 | // is v < w ? 61 | private static boolean less(Comparable v, Comparable w) { 62 | return v.compareTo(w) < 0; 63 | } 64 | 65 | /*************************************************************************** 66 | * Check if array is sorted - useful for debugging. 67 | ***************************************************************************/ 68 | private static boolean isSorted(Comparable[] a) { 69 | return isSorted(a, 0, a.length - 1); 70 | } 71 | 72 | private static boolean isSorted(Comparable[] a, int lo, int hi) { 73 | for (int i = lo + 1; i <= hi; i++) 74 | if (less(a[i], a[i-1])) return false; 75 | return true; 76 | } 77 | 78 | 79 | /*************************************************************************** 80 | * Index mergesort. 81 | ***************************************************************************/ 82 | // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi] 83 | private static void merge(Comparable[] a, int[] index, int[] aux, int lo, int mid, int hi) { 84 | 85 | // copy to aux[] 86 | for (int k = lo; k <= hi; k++) { 87 | aux[k] = index[k]; 88 | } 89 | 90 | // merge back to a[] 91 | int i = lo, j = mid+1; 92 | for (int k = lo; k <= hi; k++) { 93 | if (i > mid) index[k] = aux[j++]; 94 | else if (j > hi) index[k] = aux[i++]; 95 | else if (less(a[aux[j]], a[aux[i]])) index[k] = aux[j++]; 96 | else index[k] = aux[i++]; 97 | } 98 | } 99 | 100 | /** 101 | * Returns a permutation that gives the elements in the array in ascending order. 102 | * @param a the array 103 | * @return a permutation {@code p[]} such that {@code a[p[0]]}, {@code a[p[1]]}, 104 | * ..., {@code a[p[N-1]]} are in ascending order 105 | */ 106 | public static int[] indexSort(Comparable[] a) { 107 | int n = a.length; 108 | int[] index = new int[n]; 109 | for (int i = 0; i < n; i++) 110 | index[i] = i; 111 | 112 | int[] aux = new int[n]; 113 | sort(a, index, aux, 0, n-1); 114 | return index; 115 | } 116 | 117 | // mergesort a[lo..hi] using auxiliary array aux[lo..hi] 118 | private static void sort(Comparable[] a, int[] index, int[] aux, int lo, int hi) { 119 | if (hi <= lo) return; 120 | int mid = lo + (hi - lo) / 2; 121 | sort(a, index, aux, lo, mid); 122 | sort(a, index, aux, mid + 1, hi); 123 | merge(a, index, aux, lo, mid, hi); 124 | } 125 | 126 | // print array to standard output 127 | private static void show(Comparable[] a) { 128 | for (int i = 0; i < a.length; i++) { 129 | StdOut.println(a[i]); 130 | } 131 | } 132 | 133 | /** 134 | * Reads in a sequence of strings from standard input; mergesorts them; 135 | * and prints them to standard output in ascending order. 136 | * 137 | * @param args the command-line arguments 138 | */ 139 | public static void main(String[] args) { 140 | String[] a = StdIn.readAllStrings(); 141 | Merge.sort(a); 142 | show(a); 143 | } 144 | } -------------------------------------------------------------------------------- /Chapter 4 图 Graph/4.6 strong components (Kosaraju–Sharir).java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code KosarajuSharirSCC} class represents a data type for 3 | * determining the strong components in a digraph. 4 | * The id operation determines in which strong component 5 | * a given vertex lies; the areStronglyConnected operation 6 | * determines whether two vertices are in the same strong component; 7 | * and the count operation determines the number of strong 8 | * components. 9 | * The component identifier of a component is one of the 10 | * vertices in the strong component: two vertices have the same component 11 | * identifier if and only if they are in the same strong component. 12 | * This implementation uses the Kosaraju-Sharir algorithm. 13 | * The constructor takes time proportional to V + E 14 | * (in the worst case), 15 | * where V is the number of vertices and E is the number of edges. 16 | * Afterwards, the id, count, and areStronglyConnected 17 | * operations take constant time. 18 | * For alternate implementations of the same API, see 19 | * {@link TarjanSCC} and {@link GabowSCC}. 20 | * @author Robert Sedgewick 21 | * @author Kevin Wayne 22 | */ 23 | public class KosarajuSharirSCC { 24 | private boolean[] marked; // marked[v] = has vertex v been visited? 25 | private int[] id; // id[v] = id of strong component containing v 26 | private int count; // number of strongly-connected components 27 | 28 | /** 29 | * Computes the strong components of the digraph {@code G}. 30 | * @param G the digraph 31 | */ 32 | public KosarajuSharirSCC(Digraph G) { 33 | 34 | // compute reverse postorder of reverse graph 35 | DepthFirstOrder dfs = new DepthFirstOrder(G.reverse()); 36 | 37 | // run DFS on G, using reverse postorder to guide calculation 38 | marked = new boolean[G.V()]; 39 | id = new int[G.V()]; 40 | for (int v : dfs.reversePost()) { 41 | if (!marked[v]) { 42 | dfs(G, v); 43 | count++; 44 | } 45 | } 46 | 47 | // check that id[] gives strong components 48 | assert check(G); 49 | } 50 | 51 | // DFS on graph G 52 | private void dfs(Digraph G, int v) { 53 | marked[v] = true; 54 | id[v] = count; 55 | for (int w : G.adj(v)) { 56 | if (!marked[w]) dfs(G, w); 57 | } 58 | } 59 | 60 | /** 61 | * Returns the number of strong components. 62 | * @return the number of strong components 63 | */ 64 | public int count() { 65 | return count; 66 | } 67 | 68 | /** 69 | * Are vertices {@code v} and {@code w} in the same strong component? 70 | * @param v one vertex 71 | * @param w the other vertex 72 | * @return {@code true} if vertices {@code v} and {@code w} are in the same 73 | * strong component, and {@code false} otherwise 74 | * @throws IllegalArgumentException unless {@code 0 <= v < V} 75 | * @throws IllegalArgumentException unless {@code 0 <= w < V} 76 | */ 77 | public boolean stronglyConnected(int v, int w) { 78 | validateVertex(v); 79 | validateVertex(w); 80 | return id[v] == id[w]; 81 | } 82 | 83 | /** 84 | * Returns the component id of the strong component containing vertex {@code v}. 85 | * @param v the vertex 86 | * @return the component id of the strong component containing vertex {@code v} 87 | * @throws IllegalArgumentException unless {@code 0 <= s < V} 88 | */ 89 | public int id(int v) { 90 | validateVertex(v); 91 | return id[v]; 92 | } 93 | 94 | // does the id[] array contain the strongly connected components? 95 | private boolean check(Digraph G) { 96 | TransitiveClosure tc = new TransitiveClosure(G); 97 | for (int v = 0; v < G.V(); v++) { 98 | for (int w = 0; w < G.V(); w++) { 99 | if (stronglyConnected(v, w) != (tc.reachable(v, w) && tc.reachable(w, v))) 100 | return false; 101 | } 102 | } 103 | return true; 104 | } 105 | 106 | // throw an IllegalArgumentException unless {@code 0 <= v < V} 107 | private void validateVertex(int v) { 108 | int V = marked.length; 109 | if (v < 0 || v >= V) 110 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 111 | } 112 | 113 | /** 114 | * Unit tests the {@code KosarajuSharirSCC} data type. 115 | * 116 | * @param args the command-line arguments 117 | */ 118 | public static void main(String[] args) { 119 | In in = new In(args[0]); 120 | Digraph G = new Digraph(in); 121 | KosarajuSharirSCC scc = new KosarajuSharirSCC(G); 122 | 123 | // number of connected components 124 | int m = scc.count(); 125 | StdOut.println(m + " strong components"); 126 | 127 | // compute list of vertices in each strong component 128 | Queue[] components = (Queue[]) new Queue[m]; 129 | for (int i = 0; i < m; i++) { 130 | components[i] = new Queue(); 131 | } 132 | for (int v = 0; v < G.V(); v++) { 133 | components[scc.id(v)].enqueue(v); 134 | } 135 | 136 | // print results 137 | for (int i = 0; i < m; i++) { 138 | for (int v : components[i]) { 139 | StdOut.print(v + " "); 140 | } 141 | StdOut.println(); 142 | } 143 | 144 | } 145 | 146 | } -------------------------------------------------------------------------------- /Chapter 4 图 Graph/4.8 MST (Kruskal).java: -------------------------------------------------------------------------------- 1 | /** 2 | * The {@code KruskalMST} class represents a data type for computing a 3 | * minimum spanning tree in an edge-weighted graph. 4 | * The edge weights can be positive, zero, or negative and need not 5 | * be distinct. If the graph is not connected, it computes a minimum 6 | * spanning forest, which is the union of minimum spanning trees 7 | * in each connected component. The {@code weight()} method returns the 8 | * weight of a minimum spanning tree and the {@code edges()} method 9 | * returns its edges. 10 | * This implementation uses Krusal's algorithm and the 11 | * union-find data type. 12 | * The constructor takes time proportional to E log E 13 | * and extra space (not including the graph) proportional to V, 14 | * where V is the number of vertices and E is the number of edges. 15 | * Afterwards, the {@code weight()} method takes constant time 16 | * and the {@code edges()} method takes time proportional to V. 17 | * For alternate implementations, see {@link LazyPrimMST}, {@link PrimMST}, 18 | * and {@link BoruvkaMST}. 19 | * @author Robert Sedgewick 20 | * @author Kevin Wayne 21 | */ 22 | public class KruskalMST { 23 | private static final double FLOATING_POINT_EPSILON = 1E-12; 24 | 25 | private double weight; // weight of MST 26 | private Queue mst = new Queue(); // edges in MST 27 | 28 | /** 29 | * Compute a minimum spanning tree (or forest) of an edge-weighted graph. 30 | * @param G the edge-weighted graph 31 | */ 32 | public KruskalMST(EdgeWeightedGraph G) { 33 | // more efficient to build heap by passing array of edges 34 | MinPQ pq = new MinPQ(); 35 | for (Edge e : G.edges()) { 36 | pq.insert(e); 37 | } 38 | 39 | // run greedy algorithm 40 | UF uf = new UF(G.V()); 41 | while (!pq.isEmpty() && mst.size() < G.V() - 1) { 42 | Edge e = pq.delMin(); 43 | int v = e.either(); 44 | int w = e.other(v); 45 | if (!uf.connected(v, w)) { // v-w does not create a cycle 46 | uf.union(v, w); // merge v and w components 47 | mst.enqueue(e); // add edge e to mst 48 | weight += e.weight(); 49 | } 50 | } 51 | 52 | // check optimality conditions 53 | assert check(G); 54 | } 55 | 56 | /** 57 | * Returns the edges in a minimum spanning tree (or forest). 58 | * @return the edges in a minimum spanning tree (or forest) as 59 | * an iterable of edges 60 | */ 61 | public Iterable edges() { 62 | return mst; 63 | } 64 | 65 | /** 66 | * Returns the sum of the edge weights in a minimum spanning tree (or forest). 67 | * @return the sum of the edge weights in a minimum spanning tree (or forest) 68 | */ 69 | public double weight() { 70 | return weight; 71 | } 72 | 73 | // check optimality conditions (takes time proportional to E V lg* V) 74 | private boolean check(EdgeWeightedGraph G) { 75 | 76 | // check total weight 77 | double total = 0.0; 78 | for (Edge e : edges()) { 79 | total += e.weight(); 80 | } 81 | if (Math.abs(total - weight()) > FLOATING_POINT_EPSILON) { 82 | System.err.printf("Weight of edges does not equal weight(): %f vs. %f\n", total, weight()); 83 | return false; 84 | } 85 | 86 | // check that it is acyclic 87 | UF uf = new UF(G.V()); 88 | for (Edge e : edges()) { 89 | int v = e.either(), w = e.other(v); 90 | if (uf.connected(v, w)) { 91 | System.err.println("Not a forest"); 92 | return false; 93 | } 94 | uf.union(v, w); 95 | } 96 | 97 | // check that it is a spanning forest 98 | for (Edge e : G.edges()) { 99 | int v = e.either(), w = e.other(v); 100 | if (!uf.connected(v, w)) { 101 | System.err.println("Not a spanning forest"); 102 | return false; 103 | } 104 | } 105 | 106 | // check that it is a minimal spanning forest (cut optimality conditions) 107 | for (Edge e : edges()) { 108 | 109 | // all edges in MST except e 110 | uf = new UF(G.V()); 111 | for (Edge f : mst) { 112 | int x = f.either(), y = f.other(x); 113 | if (f != e) uf.union(x, y); 114 | } 115 | 116 | // check that e is min weight edge in crossing cut 117 | for (Edge f : G.edges()) { 118 | int x = f.either(), y = f.other(x); 119 | if (!uf.connected(x, y)) { 120 | if (f.weight() < e.weight()) { 121 | System.err.println("Edge " + f + " violates cut optimality conditions"); 122 | return false; 123 | } 124 | } 125 | } 126 | 127 | } 128 | 129 | return true; 130 | } 131 | 132 | 133 | /** 134 | * Unit tests the {@code KruskalMST} data type. 135 | * 136 | * @param args the command-line arguments 137 | */ 138 | public static void main(String[] args) { 139 | In in = new In(args[0]); 140 | EdgeWeightedGraph G = new EdgeWeightedGraph(in); 141 | KruskalMST mst = new KruskalMST(G); 142 | for (Edge e : mst.edges()) { 143 | StdOut.println(e); 144 | } 145 | StdOut.printf("%.5f\n", mst.weight()); 146 | } 147 | 148 | } -------------------------------------------------------------------------------- /chapter 1 基础 Fundamental/1.2 LIFO stack (linked list).java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.NoSuchElementException; 3 | 4 | 5 | /** 6 | * The {@code LinkedStack} class represents a last-in-first-out (LIFO) stack of 7 | * generic items. 8 | * It supports the usual push and pop operations, along with methods 9 | * for peeking at the top item, testing if the stack is empty, and iterating through 10 | * the items in LIFO order. 11 | * This implementation uses a singly-linked list with a non-static nested class for 12 | * linked-list nodes. See {@link Stack} for a version that uses a static nested class. 13 | * The push, pop, peek, size, and is-empty 14 | * operations all take constant time in the worst case. 15 | * @author Robert Sedgewick 16 | * @author Kevin Wayne 17 | */ 18 | public class LinkedStack implements Iterable { 19 | private int n; // size of the stack 20 | private Node first; // top of stack 21 | 22 | // helper linked list class 23 | private class Node { 24 | private Item item; 25 | private Node next; 26 | } 27 | 28 | /** 29 | * Initializes an empty stack. 30 | */ 31 | public LinkedStack() { 32 | first = null; 33 | n = 0; 34 | assert check(); 35 | } 36 | 37 | /** 38 | * Is this stack empty? 39 | * @return true if this stack is empty; false otherwise 40 | */ 41 | public boolean isEmpty() { 42 | return first == null; 43 | } 44 | 45 | /** 46 | * Returns the number of items in the stack. 47 | * @return the number of items in the stack 48 | */ 49 | public int size() { 50 | return n; 51 | } 52 | 53 | /** 54 | * Adds the item to this stack. 55 | * @param item the item to add 56 | */ 57 | public void push(Item item) { 58 | Node oldfirst = first; 59 | first = new Node(); 60 | first.item = item; 61 | first.next = oldfirst; 62 | n++; 63 | assert check(); 64 | } 65 | 66 | /** 67 | * Removes and returns the item most recently added to this stack. 68 | * @return the item most recently added 69 | * @throws java.util.NoSuchElementException if this stack is empty 70 | */ 71 | public Item pop() { 72 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 73 | Item item = first.item; // save item to return 74 | first = first.next; // delete first node 75 | n--; 76 | assert check(); 77 | return item; // return the saved item 78 | } 79 | 80 | 81 | /** 82 | * Returns (but does not remove) the item most recently added to this stack. 83 | * @return the item most recently added to this stack 84 | * @throws java.util.NoSuchElementException if this stack is empty 85 | */ 86 | public Item peek() { 87 | if (isEmpty()) throw new NoSuchElementException("Stack underflow"); 88 | return first.item; 89 | } 90 | 91 | /** 92 | * Returns a string representation of this stack. 93 | * @return the sequence of items in the stack in LIFO order, separated by spaces 94 | */ 95 | public String toString() { 96 | StringBuilder s = new StringBuilder(); 97 | for (Item item : this) 98 | s.append(item + " "); 99 | return s.toString(); 100 | } 101 | 102 | /** 103 | * Returns an iterator to this stack that iterates through the items in LIFO order. 104 | * @return an iterator to this stack that iterates through the items in LIFO order. 105 | */ 106 | public Iterator iterator() { 107 | return new ListIterator(); 108 | } 109 | 110 | // an iterator, doesn't implement remove() since it's optional 111 | private class ListIterator implements Iterator { 112 | private Node current = first; 113 | public boolean hasNext() { return current != null; } 114 | public void remove() { throw new UnsupportedOperationException(); } 115 | 116 | public Item next() { 117 | if (!hasNext()) throw new NoSuchElementException(); 118 | Item item = current.item; 119 | current = current.next; 120 | return item; 121 | } 122 | } 123 | 124 | 125 | // check internal invariants 126 | private boolean check() { 127 | 128 | // check a few properties of instance variable 'first' 129 | if (n < 0) { 130 | return false; 131 | } 132 | if (n == 0) { 133 | if (first != null) return false; 134 | } 135 | else if (n == 1) { 136 | if (first == null) return false; 137 | if (first.next != null) return false; 138 | } 139 | else { 140 | if (first == null) return false; 141 | if (first.next == null) return false; 142 | } 143 | 144 | // check internal consistency of instance variable n 145 | int numberOfNodes = 0; 146 | for (Node x = first; x != null && numberOfNodes <= n; x = x.next) { 147 | numberOfNodes++; 148 | } 149 | if (numberOfNodes != n) return false; 150 | 151 | return true; 152 | } 153 | 154 | /** 155 | * Unit tests the {@code LinkedStack} data type. 156 | * 157 | * @param args the command-line arguments 158 | */ 159 | public static void main(String[] args) { 160 | LinkedStack stack = new LinkedStack(); 161 | while (!StdIn.isEmpty()) { 162 | String item = StdIn.readString(); 163 | if (!item.equals("-")) 164 | stack.push(item); 165 | else if (!stack.isEmpty()) 166 | StdOut.print(stack.pop() + " "); 167 | } 168 | StdOut.println("(" + stack.size() + " left on stack)"); 169 | } 170 | } 171 | 172 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-4.2 paths in a graph (BFS).java: -------------------------------------------------------------------------------- 1 | public class BreadthFirstPaths { 2 | private static final int INFINITY = Integer.MAX_VALUE; 3 | private boolean[] marked; 4 | private int[] edgeTo; 5 | private int[] distTo; 6 | 7 | public BreadthFirstPaths(Graph G, int s) { 8 | marked = new boolean[G.V()]; 9 | distTo = new int[G.V()]; 10 | edgeTo = new int[G.V()]; 11 | validateVertex(s); 12 | bfs(G, s); 13 | 14 | assert check(G, s); 15 | } 16 | 17 | public BreadthFirstPaths(Graph G, Iterable sources) { 18 | marked = new boolean[G.V()]; 19 | distTo = new int[G.V()]; 20 | edgeTo = new int[G.V()]; 21 | for (int v = 0; v < G.V(); v++) 22 | distTo[v] = INFINITY; 23 | validateVertices(sources); 24 | bfs(G, sources); 25 | } 26 | 27 | 28 | private void bfs(Graph G, int s) { 29 | Queue q = new Queue(); 30 | for (int v = 0; v < G.V(); v++) 31 | distTo[v] = INFINITY; 32 | distTo[s] = 0; 33 | marked[s] = true; 34 | q.enqueue(s); 35 | 36 | while (!q.isEmpty()) { 37 | int v = q.dequeue(); 38 | for (int w : G.adj(v)) { 39 | if (!marked[w]) { 40 | edgeTo[w] = v; 41 | distTo[w] = distTo[v] + 1; 42 | marked[w] = true; 43 | q.enqueue(w); 44 | } 45 | } 46 | } 47 | } 48 | 49 | private void bfs(Graph G, Iterable sources) { 50 | Queue q = new Queue(); 51 | for (int s : sources) { 52 | marked[s] = true; 53 | distTo[s] = 0; 54 | q.enqueue(s); 55 | } 56 | while (!q.isEmpty()) { 57 | int v = q.dequeue(); 58 | for (int w : G.adj(v)) { 59 | if (!marked[w]) { 60 | edgeTo[w] = v; 61 | distTo[w] = distTo[v] + 1; 62 | marked[w] = true; 63 | q.enqueue(w); 64 | } 65 | } 66 | } 67 | } 68 | 69 | public boolean hasPathTo(int v) { 70 | validateVertex(v); 71 | return marked[v]; 72 | } 73 | 74 | public int distTo(int v) { 75 | validateVertex(v); 76 | return distTo[v]; 77 | } 78 | 79 | public Iterable pathTo(int v) { 80 | validateVertex(v); 81 | if (!hasPathTo(v)) return null; 82 | Stack path = new Stack(); 83 | int x; 84 | for (x = v; distTo[x] != 0; x = edgeTo[x]) 85 | path.push(x); 86 | path.push(x); 87 | return path; 88 | } 89 | 90 | 91 | private boolean check(Graph G, int s) { 92 | 93 | if (distTo[s] != 0) { 94 | StdOut.println("distance of source " + s + " to itself = " + distTo[s]); 95 | return false; 96 | } 97 | 98 | for (int v = 0; v < G.V(); v++) { 99 | for (int w : G.adj(v)) { 100 | if (hasPathTo(v) != hasPathTo(w)) { 101 | StdOut.println("edge " + v + "-" + w); 102 | StdOut.println("hasPathTo(" + v + ") = " + hasPathTo(v)); 103 | StdOut.println("hasPathTo(" + w + ") = " + hasPathTo(w)); 104 | return false; 105 | } 106 | if (hasPathTo(v) && (distTo[w] > distTo[v] + 1)) { 107 | StdOut.println("edge " + v + "-" + w); 108 | StdOut.println("distTo[" + v + "] = " + distTo[v]); 109 | StdOut.println("distTo[" + w + "] = " + distTo[w]); 110 | return false; 111 | } 112 | } 113 | } 114 | 115 | for (int w = 0; w < G.V(); w++) { 116 | if (!hasPathTo(w) || w == s) continue; 117 | int v = edgeTo[w]; 118 | if (distTo[w] != distTo[v] + 1) { 119 | StdOut.println("shortest path edge " + v + "-" + w); 120 | StdOut.println("distTo[" + v + "] = " + distTo[v]); 121 | StdOut.println("distTo[" + w + "] = " + distTo[w]); 122 | return false; 123 | } 124 | } 125 | 126 | return true; 127 | } 128 | 129 | private void validateVertex(int v) { 130 | int V = marked.length; 131 | if (v < 0 || v >= V) 132 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 133 | } 134 | 135 | private void validateVertices(Iterable vertices) { 136 | if (vertices == null) { 137 | throw new IllegalArgumentException("argument is null"); 138 | } 139 | int V = marked.length; 140 | for (int v : vertices) { 141 | if (v < 0 || v >= V) { 142 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 143 | } 144 | } 145 | } 146 | 147 | public static void main(String[] args) { 148 | In in = new In(args[0]); 149 | Graph G = new Graph(in); 150 | 151 | int s = Integer.parseInt(args[1]); 152 | BreadthFirstPaths bfs = new BreadthFirstPaths(G, s); 153 | 154 | for (int v = 0; v < G.V(); v++) { 155 | if (bfs.hasPathTo(v)) { 156 | StdOut.printf("%d to %d (%d): ", s, v, bfs.distTo(v)); 157 | for (int x : bfs.pathTo(v)) { 158 | if (x == s) StdOut.print(x); 159 | else StdOut.print("-" + x); 160 | } 161 | StdOut.println(); 162 | } 163 | 164 | else { 165 | StdOut.printf("%d to %d (-): not connected\n", s, v); 166 | } 167 | 168 | } 169 | } 170 | 171 | 172 | } 173 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-5.4 multiway trie symbol table.java: -------------------------------------------------------------------------------- 1 | public class TrieST { 2 | private static final int R = 256; 3 | 4 | 5 | private Node root; 6 | private int n; 7 | 8 | private static class Node { 9 | private Object val; 10 | private Node[] next = new Node[R]; 11 | } 12 | 13 | public TrieST() { 14 | } 15 | 16 | 17 | public Value get(String key) { 18 | Node x = get(root, key, 0); 19 | if (x == null) return null; 20 | return (Value) x.val; 21 | } 22 | 23 | public boolean contains(String key) { 24 | return get(key) != null; 25 | } 26 | 27 | private Node get(Node x, String key, int d) { 28 | if (x == null) return null; 29 | if (d == key.length()) return x; 30 | char c = key.charAt(d); 31 | return get(x.next[c], key, d+1); 32 | } 33 | 34 | public void put(String key, Value val) { 35 | if (val == null) delete(key); 36 | else root = put(root, key, val, 0); 37 | } 38 | 39 | private Node put(Node x, String key, Value val, int d) { 40 | if (x == null) x = new Node(); 41 | if (d == key.length()) { 42 | if (x.val == null) n++; 43 | x.val = val; 44 | return x; 45 | } 46 | char c = key.charAt(d); 47 | x.next[c] = put(x.next[c], key, val, d+1); 48 | return x; 49 | } 50 | 51 | public int size() { 52 | return n; 53 | } 54 | 55 | public boolean isEmpty() { 56 | return size() == 0; 57 | } 58 | 59 | public Iterable keys() { 60 | return keysWithPrefix(""); 61 | } 62 | 63 | public Iterable keysWithPrefix(String prefix) { 64 | Queue results = new Queue(); 65 | Node x = get(root, prefix, 0); 66 | collect(x, new StringBuilder(prefix), results); 67 | return results; 68 | } 69 | 70 | private void collect(Node x, StringBuilder prefix, Queue results) { 71 | if (x == null) return; 72 | if (x.val != null) results.enqueue(prefix.toString()); 73 | for (char c = 0; c < R; c++) { 74 | prefix.append(c); 75 | collect(x.next[c], prefix, results); 76 | prefix.deleteCharAt(prefix.length() - 1); 77 | } 78 | } 79 | 80 | public Iterable keysThatMatch(String pattern) { 81 | Queue results = new Queue(); 82 | collect(root, new StringBuilder(), pattern, results); 83 | return results; 84 | } 85 | 86 | private void collect(Node x, StringBuilder prefix, String pattern, Queue results) { 87 | if (x == null) return; 88 | int d = prefix.length(); 89 | if (d == pattern.length() && x.val != null) 90 | results.enqueue(prefix.toString()); 91 | if (d == pattern.length()) 92 | return; 93 | char c = pattern.charAt(d); 94 | if (c == '.') { 95 | for (char ch = 0; ch < R; ch++) { 96 | prefix.append(ch); 97 | collect(x.next[ch], prefix, pattern, results); 98 | prefix.deleteCharAt(prefix.length() - 1); 99 | } 100 | } 101 | else { 102 | prefix.append(c); 103 | collect(x.next[c], prefix, pattern, results); 104 | prefix.deleteCharAt(prefix.length() - 1); 105 | } 106 | } 107 | 108 | public String longestPrefixOf(String query) { 109 | int length = longestPrefixOf(root, query, 0, -1); 110 | if (length == -1) return null; 111 | else return query.substring(0, length); 112 | } 113 | 114 | private int longestPrefixOf(Node x, String query, int d, int length) { 115 | if (x == null) return length; 116 | if (x.val != null) length = d; 117 | if (d == query.length()) return length; 118 | char c = query.charAt(d); 119 | return longestPrefixOf(x.next[c], query, d+1, length); 120 | } 121 | 122 | public void delete(String key) { 123 | root = delete(root, key, 0); 124 | } 125 | 126 | private Node delete(Node x, String key, int d) { 127 | if (x == null) return null; 128 | if (d == key.length()) { 129 | if (x.val != null) n--; 130 | x.val = null; 131 | } 132 | else { 133 | char c = key.charAt(d); 134 | x.next[c] = delete(x.next[c], key, d+1); 135 | } 136 | 137 | if (x.val != null) return x; 138 | for (int c = 0; c < R; c++) 139 | if (x.next[c] != null) 140 | return x; 141 | return null; 142 | } 143 | 144 | public static void main(String[] args) { 145 | 146 | TrieST st = new TrieST(); 147 | for (int i = 0; !StdIn.isEmpty(); i++) { 148 | String key = StdIn.readString(); 149 | st.put(key, i); 150 | } 151 | 152 | if (st.size() < 100) { 153 | StdOut.println("keys(\"\"):"); 154 | for (String key : st.keys()) { 155 | StdOut.println(key + " " + st.get(key)); 156 | } 157 | StdOut.println(); 158 | } 159 | 160 | StdOut.println("longestPrefixOf(\"shellsort\"):"); 161 | StdOut.println(st.longestPrefixOf("shellsort")); 162 | StdOut.println(); 163 | 164 | StdOut.println("longestPrefixOf(\"quicksort\"):"); 165 | StdOut.println(st.longestPrefixOf("quicksort")); 166 | StdOut.println(); 167 | 168 | StdOut.println("keysWithPrefix(\"shor\"):"); 169 | for (String s : st.keysWithPrefix("shor")) 170 | StdOut.println(s); 171 | StdOut.println(); 172 | 173 | StdOut.println("keysThatMatch(\".he.l.\"):"); 174 | for (String s : st.keysThatMatch(".he.l.")) 175 | StdOut.println(s); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /Non-Comment版本/nonComment-6.4 maxflow–mincut.java: -------------------------------------------------------------------------------- 1 | public class FordFulkerson { 2 | private static final double FLOATING_POINT_EPSILON = 1E-11; 3 | 4 | private final int V; 5 | private boolean[] marked; 6 | private FlowEdge[] edgeTo; 7 | private double value; 8 | 9 | public FordFulkerson(FlowNetwork G, int s, int t) { 10 | V = G.V(); 11 | validate(s); 12 | validate(t); 13 | if (s == t) throw new IllegalArgumentException("Source equals sink"); 14 | if (!isFeasible(G, s, t)) throw new IllegalArgumentException("Initial flow is infeasible"); 15 | 16 | value = excess(G, t); 17 | while (hasAugmentingPath(G, s, t)) { 18 | 19 | double bottle = Double.POSITIVE_INFINITY; 20 | for (int v = t; v != s; v = edgeTo[v].other(v)) { 21 | bottle = Math.min(bottle, edgeTo[v].residualCapacityTo(v)); 22 | } 23 | 24 | for (int v = t; v != s; v = edgeTo[v].other(v)) { 25 | edgeTo[v].addResidualFlowTo(v, bottle); 26 | } 27 | 28 | value += bottle; 29 | } 30 | 31 | assert check(G, s, t); 32 | } 33 | 34 | public double value() { 35 | return value; 36 | } 37 | 38 | public boolean inCut(int v) { 39 | validate(v); 40 | return marked[v]; 41 | } 42 | 43 | private void validate(int v) { 44 | if (v < 0 || v >= V) 45 | throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); 46 | } 47 | 48 | 49 | private boolean hasAugmentingPath(FlowNetwork G, int s, int t) { 50 | edgeTo = new FlowEdge[G.V()]; 51 | marked = new boolean[G.V()]; 52 | 53 | Queue queue = new Queue(); 54 | queue.enqueue(s); 55 | marked[s] = true; 56 | while (!queue.isEmpty() && !marked[t]) { 57 | int v = queue.dequeue(); 58 | 59 | for (FlowEdge e : G.adj(v)) { 60 | int w = e.other(v); 61 | 62 | if (e.residualCapacityTo(w) > 0) { 63 | if (!marked[w]) { 64 | edgeTo[w] = e; 65 | marked[w] = true; 66 | queue.enqueue(w); 67 | } 68 | } 69 | } 70 | } 71 | 72 | return marked[t]; 73 | } 74 | 75 | 76 | 77 | private double excess(FlowNetwork G, int v) { 78 | double excess = 0.0; 79 | for (FlowEdge e : G.adj(v)) { 80 | if (v == e.from()) excess -= e.flow(); 81 | else excess += e.flow(); 82 | } 83 | return excess; 84 | } 85 | 86 | private boolean isFeasible(FlowNetwork G, int s, int t) { 87 | 88 | for (int v = 0; v < G.V(); v++) { 89 | for (FlowEdge e : G.adj(v)) { 90 | if (e.flow() < -FLOATING_POINT_EPSILON || e.flow() > e.capacity() + FLOATING_POINT_EPSILON) { 91 | System.err.println("Edge does not satisfy capacity constraints: " + e); 92 | return false; 93 | } 94 | } 95 | } 96 | 97 | if (Math.abs(value + excess(G, s)) > FLOATING_POINT_EPSILON) { 98 | System.err.println("Excess at source = " + excess(G, s)); 99 | System.err.println("Max flow = " + value); 100 | return false; 101 | } 102 | if (Math.abs(value - excess(G, t)) > FLOATING_POINT_EPSILON) { 103 | System.err.println("Excess at sink = " + excess(G, t)); 104 | System.err.println("Max flow = " + value); 105 | return false; 106 | } 107 | for (int v = 0; v < G.V(); v++) { 108 | if (v == s || v == t) continue; 109 | else if (Math.abs(excess(G, v)) > FLOATING_POINT_EPSILON) { 110 | System.err.println("Net flow out of " + v + " doesn't equal zero"); 111 | return false; 112 | } 113 | } 114 | return true; 115 | } 116 | 117 | 118 | 119 | private boolean check(FlowNetwork G, int s, int t) { 120 | 121 | if (!isFeasible(G, s, t)) { 122 | System.err.println("Flow is infeasible"); 123 | return false; 124 | } 125 | 126 | if (!inCut(s)) { 127 | System.err.println("source " + s + " is not on source side of min cut"); 128 | return false; 129 | } 130 | if (inCut(t)) { 131 | System.err.println("sink " + t + " is on source side of min cut"); 132 | return false; 133 | } 134 | 135 | double mincutValue = 0.0; 136 | for (int v = 0; v < G.V(); v++) { 137 | for (FlowEdge e : G.adj(v)) { 138 | if ((v == e.from()) && inCut(e.from()) && !inCut(e.to())) 139 | mincutValue += e.capacity(); 140 | } 141 | } 142 | 143 | if (Math.abs(mincutValue - value) > FLOATING_POINT_EPSILON) { 144 | System.err.println("Max flow value = " + value + ", min cut value = " + mincutValue); 145 | return false; 146 | } 147 | 148 | return true; 149 | } 150 | 151 | 152 | public static void main(String[] args) { 153 | 154 | int V = Integer.parseInt(args[0]); 155 | int E = Integer.parseInt(args[1]); 156 | int s = 0, t = V-1; 157 | FlowNetwork G = new FlowNetwork(V, E); 158 | StdOut.println(G); 159 | 160 | FordFulkerson maxflow = new FordFulkerson(G, s, t); 161 | StdOut.println("Max flow from " + s + " to " + t); 162 | for (int v = 0; v < G.V(); v++) { 163 | for (FlowEdge e : G.adj(v)) { 164 | if ((v == e.from()) && e.flow() > 0) 165 | StdOut.println(" " + e); 166 | } 167 | } 168 | 169 | StdOut.print("Min cut: "); 170 | for (int v = 0; v < G.V(); v++) { 171 | if (maxflow.inCut(v)) StdOut.print(v + " "); 172 | } 173 | StdOut.println(); 174 | 175 | StdOut.println("Max flow value = " + maxflow.value()); 176 | } 177 | 178 | } 179 | --------------------------------------------------------------------------------