├── docs ├── ch02 │ └── index.md ├── ch03 │ └── index.md ├── ch05 │ └── index.md ├── ch06 │ └── index.md ├── ch07 │ └── index.md ├── ch08 │ └── index.md ├── ch09 │ └── index.md ├── ch10 │ └── index.md ├── ch11 │ └── index.md ├── ch12 │ └── index.md ├── ch13 │ └── index.md ├── ch14 │ └── index.md ├── ch15 │ └── index.md ├── ch04 │ ├── loop_invariant.png │ └── index.md ├── README.md └── ch01 │ └── index.md ├── ch05 ├── build.gradle └── src │ └── main │ └── java │ ├── BinarySearchDemo.java │ ├── Factorial.java │ ├── DiskUsageDemo.java │ ├── EnglishRuler.java │ └── AnalyzingRecursion.java ├── ch07 ├── build.gradle └── src │ └── main │ └── java │ ├── Position.java │ ├── Test.java │ ├── SortingPositionalList.java │ ├── List.java │ ├── FavoritesListMTF.java │ ├── PositionalList.java │ └── FavoritesList.java ├── ch13 ├── build.gradle └── src │ └── main │ └── java │ ├── MatrixChain.java │ ├── LCS.java │ └── PatternMatching.java ├── ch15 └── build.gradle ├── ch03 ├── build.gradle └── src │ └── main │ └── java │ ├── GameEntry.java │ ├── InsertionSort.java │ ├── ScoreBoard.java │ ├── CaesarCipher.java │ ├── CircularlyLinkedList.java │ ├── TicTacToe.java │ ├── DoublyLinkedList.java │ └── SinglyLinkedList.java ├── ch06 ├── build.gradle └── src │ └── main │ └── java │ ├── Queue.java │ ├── CircularQueue.java │ ├── LinkedQueue.java │ ├── LinkedCircularQueue.java │ ├── Stack.java │ ├── ArrayStack.java │ ├── StackUsageDemo.java │ ├── Deque.java │ ├── JosephusProblem.java │ ├── ArrayQueue.java │ ├── MatchingTags.java │ ├── CircularlyLinkedList.java │ ├── LinkedStack.java │ └── SinglyLinkedList.java ├── class-diagram.ldb ├── _config.yml ├── ch02 ├── src │ └── main │ │ └── java │ │ ├── A.java │ │ ├── B.java │ │ ├── Person.java │ │ ├── Insurable.java │ │ ├── Pair.java │ │ ├── GenericDemo.java │ │ ├── ObjectPair.java │ │ ├── Transportable.java │ │ ├── GeometricProgression.java │ │ ├── Sellable.java │ │ ├── FibonacciProgression.java │ │ ├── ArithmeticProgression.java │ │ ├── ExceptionDemo.java │ │ ├── AbstractProgression.java │ │ ├── Photograph.java │ │ ├── Student.java │ │ ├── BoxedItem.java │ │ ├── Progression.java │ │ ├── BoxedItem2.java │ │ ├── TestProgression.java │ │ ├── PredatoryCreditCard.java │ │ └── CreditCard.java └── build.gradle ├── ch04 ├── build.gradle └── src │ └── main │ └── java │ ├── StringConcat.java │ ├── PrefixAverage.java │ └── StringExperiment.java ├── class-diagram.EAP ├── ch10 ├── build.gradle └── src │ └── main │ └── java │ ├── Map.java │ ├── WordCount.java │ ├── CostPerformanceDatabase.java │ ├── AbstractHashMap.java │ ├── HashMultimap.java │ ├── AbstractMap.java │ ├── UnsortedTableMap.java │ ├── ChainHashMap.java │ ├── AbstractSortedMap.java │ ├── SortedMap.java │ └── SortedTableMap.java ├── ch12 ├── build.gradle └── src │ └── main │ └── java │ ├── QuickSort.java │ └── MergeSort.java ├── ch09 ├── build.gradle └── src │ └── main │ └── java │ ├── DefaultComparator.java │ ├── Entry.java │ ├── SortedPriorityQueue.java │ ├── UnsortedPriorityQueue.java │ ├── AbstractPriorityQueue.java │ ├── PriorityQueue.java │ ├── AdaptablePriorityQueue.java │ ├── HeapAdaptablePriorityQueue.java │ └── HeapPriorityQueue.java ├── ch08 ├── build.gradle └── src │ └── main │ └── java │ ├── Tree.java │ ├── BinaryTree.java │ ├── AbstractBinaryTree.java │ ├── TraversalExamples.java │ └── AbstractTree.java ├── .prettierrc ├── ch11 ├── build.gradle └── src │ └── main │ └── java │ ├── SplayTreeMap.java │ └── AVLTreeMap.java ├── ch14 ├── build.gradle └── src │ └── main │ └── java │ ├── Edge.java │ ├── Vertex.java │ ├── Partition.java │ └── Graph.java ├── ch01 ├── build.gradle └── src │ └── main │ └── java │ ├── IsMultipleDemo.java │ ├── OnePointFive.java │ ├── IsEvenDemo.java │ ├── Main.java │ ├── OnePointSix.java │ ├── CloneDemo.java │ └── CreditCard.java ├── settings.gradle ├── .gitignore ├── .editorconfig └── .gitattributes /docs/ch02/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch03/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch05/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch06/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch07/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch08/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch09/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch10/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch11/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch12/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch13/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch14/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /docs/ch15/index.md: -------------------------------------------------------------------------------- 1 | # Exercises 2 | -------------------------------------------------------------------------------- /ch05/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | -------------------------------------------------------------------------------- /ch07/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | -------------------------------------------------------------------------------- /ch13/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | -------------------------------------------------------------------------------- /ch15/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | -------------------------------------------------------------------------------- /ch03/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | -------------------------------------------------------------------------------- /ch06/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | -------------------------------------------------------------------------------- /class-diagram.ldb: -------------------------------------------------------------------------------- 1 | KRAIT admin -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker 2 | markdown: kramdown 3 | kramdown: 4 | math_engine: mathjax 5 | -------------------------------------------------------------------------------- /ch02/src/main/java/A.java: -------------------------------------------------------------------------------- 1 | public interface A { 2 | 3 | } 4 | /*public interface A extends B{ 5 | }*/ 6 | -------------------------------------------------------------------------------- /ch02/src/main/java/B.java: -------------------------------------------------------------------------------- 1 | public interface B { 2 | 3 | } 4 | /*public interface B extends A { 5 | }*/ 6 | -------------------------------------------------------------------------------- /ch04/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | -------------------------------------------------------------------------------- /class-diagram.EAP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdouzwt/data-structures-and-algorithms-in-java/HEAD/class-diagram.EAP -------------------------------------------------------------------------------- /ch10/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | dependencies { 6 | implementation project(':ch09') 7 | } 8 | -------------------------------------------------------------------------------- /ch12/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | dependencies { 6 | implementation project(':ch06') 7 | } 8 | -------------------------------------------------------------------------------- /ch09/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | dependencies { 6 | implementation project(':ch07') 7 | } 8 | 9 | -------------------------------------------------------------------------------- /ch02/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/ch04/loop_invariant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdouzwt/data-structures-and-algorithms-in-java/HEAD/docs/ch04/loop_invariant.png -------------------------------------------------------------------------------- /ch02/src/main/java/Person.java: -------------------------------------------------------------------------------- 1 | public interface Person { 2 | boolean equals(Person other); 3 | 4 | String getName(); 5 | 6 | int getAge(); 7 | } 8 | -------------------------------------------------------------------------------- /ch06/src/main/java/Queue.java: -------------------------------------------------------------------------------- 1 | public interface Queue { 2 | int size(); 3 | 4 | boolean isEmpty(); 5 | 6 | void enqueue(E e); 7 | 8 | E first(); 9 | 10 | E dequeue(); 11 | } 12 | -------------------------------------------------------------------------------- /ch08/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | dependencies{ 6 | implementation project(':ch04') 7 | implementation project(':ch06') 8 | implementation project(':ch07') 9 | } 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | # Prettier configuration 2 | 3 | printWidth: 140 4 | singleQuote: true 5 | tabWidth: 2 6 | useTabs: false 7 | 8 | # js and ts rules: 9 | arrowParens: avoid 10 | 11 | # jsx and tsx rules: 12 | jsxBracketSameLine: false 13 | -------------------------------------------------------------------------------- /ch02/src/main/java/Insurable.java: -------------------------------------------------------------------------------- 1 | public interface Insurable extends Sellable, Transportable { 2 | 3 | /** 4 | * Returns insured value in cents. 5 | * 6 | * @return insured value 7 | */ 8 | int insuredValue(); 9 | } 10 | -------------------------------------------------------------------------------- /ch11/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | dependencies { 6 | implementation project(':ch07') 7 | implementation project(':ch08') 8 | implementation project(':ch09') 9 | implementation project(':ch10') 10 | } 11 | -------------------------------------------------------------------------------- /ch14/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | dependencies { 6 | implementation project(':ch06') 7 | implementation project(':ch07') 8 | implementation project(':ch09') 9 | implementation project(':ch10') 10 | } 11 | -------------------------------------------------------------------------------- /ch06/src/main/java/CircularQueue.java: -------------------------------------------------------------------------------- 1 | public interface CircularQueue extends Queue{ 2 | 3 | /** 4 | * Rotates teh front element of the queue to the back of the queue. 5 | * This does nothing if the queue is empty. 6 | */ 7 | void rotate(); 8 | } 9 | -------------------------------------------------------------------------------- /ch01/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | tasks.withType(JavaCompile) { 6 | options.encoding = 'UTF-8' 7 | } 8 | tasks.withType(Javadoc) { 9 | options.encoding = 'UTF-8' 10 | } 11 | 12 | 13 | repositories { 14 | mavenCentral() 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch09/src/main/java/DefaultComparator.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | public class DefaultComparator implements Comparator { 4 | 5 | @Override 6 | public int compare(E a, E b) throws ClassCastException { 7 | return ((Comparable)a).compareTo(b); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ch09/src/main/java/Entry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for key-value pair. 3 | * 4 | * @param key 5 | * @param value 6 | */ 7 | public interface Entry { 8 | K getKey(); // returns the key stored in this entry 9 | 10 | V getValue(); // returns the value stored in this entry 11 | 12 | } 13 | -------------------------------------------------------------------------------- /ch07/src/main/java/Position.java: -------------------------------------------------------------------------------- 1 | public interface Position { 2 | 3 | /** 4 | * Returns the element stored at this position. 5 | * 6 | * @return the stored element 7 | * @throws IllegalStateException if position no longer valid. 8 | */ 9 | E getElement() throws IllegalStateException; 10 | } 11 | -------------------------------------------------------------------------------- /ch10/src/main/java/Map.java: -------------------------------------------------------------------------------- 1 | public interface Map { 2 | int size(); 3 | 4 | boolean isEmpty(); 5 | 6 | V get(K key); 7 | 8 | V put(K key, V value); 9 | 10 | V remove(K key); 11 | 12 | Iterable keySet(); 13 | 14 | Iterable values(); 15 | 16 | Iterable> entrySet(); 17 | } 18 | -------------------------------------------------------------------------------- /ch02/src/main/java/Pair.java: -------------------------------------------------------------------------------- 1 | public class Pair { 2 | A first; 3 | B second; 4 | 5 | public Pair(A first, B second) { 6 | this.first = first; 7 | this.second = second; 8 | } 9 | 10 | public A getFirst() { 11 | return first; 12 | } 13 | 14 | public B getSecond() { 15 | return second; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'data-structures-and-algorithms-in-java' 2 | include 'ch01' 3 | include 'ch02' 4 | include 'ch03' 5 | include 'ch04' 6 | include 'ch05' 7 | include 'ch06' 8 | include 'ch07' 9 | include 'ch08' 10 | include 'ch09' 11 | include 'ch10' 12 | include 'ch11' 13 | include 'ch12' 14 | include 'ch13' 15 | include 'ch14' 16 | include 'ch15' 17 | 18 | -------------------------------------------------------------------------------- /ch02/src/main/java/GenericDemo.java: -------------------------------------------------------------------------------- 1 | public class GenericDemo { 2 | // 类型参数需要紧接着放在返回值类型前面,返回值类型必须紧接着放在方法名前面 3 | public static void reverse(T[] data) { 4 | int low = 0, high = data.length - 1; 5 | while (low < high) { 6 | T temp = data[low]; 7 | data[low++] = data[high]; 8 | data[high--] = temp; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch02/src/main/java/ObjectPair.java: -------------------------------------------------------------------------------- 1 | public class ObjectPair { 2 | Object first; 3 | Object second; 4 | 5 | public ObjectPair(Object first, Object second) { 6 | this.first = first; 7 | this.second = second; 8 | } 9 | 10 | public Object getFirst() { 11 | return first; 12 | } 13 | 14 | public Object getSecond() { 15 | return second; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch02/src/main/java/Transportable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for objects that can be transported. 3 | */ 4 | public interface Transportable { 5 | 6 | /** 7 | * Returns the weight in grams. 8 | * @return weight 9 | */ 10 | int weight(); 11 | 12 | /** 13 | * Returns whether the object is hazardous. 危险的;有害的。 14 | * @return 是否有害 15 | */ 16 | boolean isHazardous(); 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | *.iml 4 | out 5 | build 6 | gradle 7 | gradlew* 8 | *.class 9 | transaction-logs 10 | .project 11 | .settings 12 | target 13 | .classpath 14 | WebContent 15 | bin 16 | 17 | # Mobile Tools for Java (J2ME) 18 | .mtj.tmp/ 19 | 20 | # Package Files # 21 | *.jar 22 | *.war 23 | *.ear 24 | *.log 25 | 26 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 27 | hs_err_pid* 28 | 29 | gradlew 30 | gradlew.bat 31 | .DS_Store 32 | generated -------------------------------------------------------------------------------- /ch02/src/main/java/GeometricProgression.java: -------------------------------------------------------------------------------- 1 | public class GeometricProgression extends Progression { 2 | protected long base; 3 | 4 | public GeometricProgression() { 5 | this(2, 1); 6 | } 7 | 8 | public GeometricProgression(long b) { 9 | this(b, 1); 10 | } 11 | 12 | public GeometricProgression(long b, long start) { 13 | super(start); 14 | base = b; 15 | } 16 | 17 | @Override 18 | protected void advance() { 19 | current *= base; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch02/src/main/java/Sellable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for objects that can be sold. 3 | */ 4 | public interface Sellable { 5 | 6 | /** 7 | * Returns a description of the object. 8 | */ 9 | String description(); 10 | 11 | /** 12 | * Returns the list price in cents. 13 | * @return price 14 | */ 15 | int listPrice(); 16 | 17 | /** 18 | * Returns the lowest price in cents we will accept. 19 | * @return lowest price 20 | */ 21 | int lowestPrice(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /docs/ch04/index.md: -------------------------------------------------------------------------------- 1 | # 1.10 Exercises 2 | ### Reinforcement 3 | R-1.1 Write a short Java method, `inputAllBaseTypes`, that inputs a different value of each base type from the standard 4 | input device and prints it back to the standard output device. 5 | R-1.2 Suppose that we create an array `A` of `GameEntry` objects, which has an integer `scores` field, and we clone `A` and 6 | store the result in an array `B`. If we then immediately set `A[4].scores` equal to 550, what is the score value of the 7 | `GameEntry` object referenced by `B[4]`? 8 | -------------------------------------------------------------------------------- /ch02/src/main/java/FibonacciProgression.java: -------------------------------------------------------------------------------- 1 | public class FibonacciProgression extends Progression { 2 | protected long prev; 3 | 4 | /** */ 5 | public FibonacciProgression() { 6 | this(0, 1); 7 | } 8 | 9 | public FibonacciProgression(long first, long second) { 10 | super(first); 11 | prev = second - first; // fictitious value preceding the first 12 | } 13 | 14 | @Override 15 | protected void advance() { 16 | long temp = prev; 17 | prev = current; 18 | current += temp; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch02/src/main/java/ArithmeticProgression.java: -------------------------------------------------------------------------------- 1 | public class ArithmeticProgression extends Progression { 2 | 3 | protected long increment; 4 | 5 | public ArithmeticProgression() { 6 | this(1, 0); 7 | } 8 | 9 | public ArithmeticProgression(long stepSize) { 10 | this(stepSize, 0); 11 | } 12 | 13 | public ArithmeticProgression(long stepSize, long start) { 14 | super(start); 15 | this.increment = stepSize; 16 | } 17 | 18 | @Override 19 | protected void advance() { 20 | current += increment; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # We recommend you to keep these unchanged 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | # Change these settings to your own preference 16 | indent_style = space 17 | indent_size = 4 18 | 19 | [*.{ts, tsx, js, jsx, json, css, scss, yml}] 20 | indent_size = 2 21 | 22 | [*.md] 23 | trim_trailing_whitespace = false 24 | -------------------------------------------------------------------------------- /ch05/src/main/java/BinarySearchDemo.java: -------------------------------------------------------------------------------- 1 | public class BinarySearchDemo { 2 | 3 | // trivial binary search implementation 4 | public static boolean binarySearch(int[] data, int target, int low, int high) { 5 | if (low > high) 6 | return false; 7 | else { 8 | int mid = (low + high) / 2; 9 | if (target == data[mid]) 10 | return true; 11 | else if (target < data[mid]) 12 | return binarySearch(data, target, low, mid - 1); 13 | else 14 | return binarySearch(data, target, mid + 1, high); 15 | } 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /ch05/src/main/java/Factorial.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Factorial { 4 | 5 | public static void main(String[] args) { 6 | System.out.println("输入要求阶乘的数 n :"); 7 | Scanner stdIn = new Scanner(System.in); 8 | System.out.println(factorial(stdIn.nextInt())); 9 | } 10 | 11 | public static int factorial(int n) throws IllegalArgumentException { 12 | if (n < 0) 13 | throw new IllegalArgumentException(); // argument must be nonnegative 14 | else if (n == 0) 15 | return 1; // base case 16 | else 17 | return n * factorial(n - 1); // recursive case 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch05/src/main/java/DiskUsageDemo.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | 3 | public class DiskUsageDemo { 4 | 5 | public static long diskUsage(File root) { 6 | long total = root.length(); 7 | if (root.isDirectory()) { 8 | for (String childname : root.list()) { 9 | File child = new File(root, childname); 10 | total += diskUsage(child); 11 | } 12 | } 13 | System.out.println(total + "\t" + root); 14 | return total; 15 | } 16 | 17 | public static void main(String[] args) { 18 | File Desktop = new File("C:\\Users\\tao\\Desktop"); 19 | System.out.println(diskUsage(Desktop)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch02/src/main/java/ExceptionDemo.java: -------------------------------------------------------------------------------- 1 | public class ExceptionDemo { 2 | private static final int DEFAULT = 1; 3 | 4 | public static void main(String[] args) { 5 | int n = DEFAULT; 6 | try { 7 | n = Integer.parseInt(args[0]); 8 | if (n <= 0) { 9 | System.out.println("n must be positive. Using default."); 10 | n = DEFAULT; 11 | } 12 | } catch (ArrayIndexOutOfBoundsException e) { 13 | System.out.println("No argument specified for n. Using default."); 14 | } catch (NumberFormatException e) { 15 | System.out.println("Invalid integer argument. Using default."); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch02/src/main/java/AbstractProgression.java: -------------------------------------------------------------------------------- 1 | public abstract class AbstractProgression { 2 | protected long current; 3 | 4 | public AbstractProgression() { 5 | this(0); 6 | } 7 | 8 | public AbstractProgression(long start) { 9 | current = start; 10 | } 11 | 12 | public long nextValue() { 13 | long answer = current; 14 | advance(); 15 | return answer; 16 | } 17 | 18 | public void printProgression(int n) { 19 | System.out.print(nextValue()); 20 | for (int j = 1; j < n; j++) { 21 | System.out.print(" " + nextValue()); 22 | } 23 | System.out.println(); 24 | } 25 | 26 | protected abstract void advance(); 27 | } 28 | -------------------------------------------------------------------------------- /ch03/src/main/java/GameEntry.java: -------------------------------------------------------------------------------- 1 | public class GameEntry { 2 | private String name; // name of the person earning this score 3 | private int score; // the score value 4 | 5 | /** Constructs a game entry with given parameters.. */ 6 | public GameEntry(String name, int score) { 7 | this.name = name; 8 | this.score = score; 9 | } 10 | 11 | public String getName() { 12 | return name; 13 | } 14 | 15 | public int getScore() { 16 | return score; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "GameEntry{" + 22 | "name='" + name + '\'' + 23 | ", score=" + score + 24 | '}'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch06/src/main/java/LinkedQueue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Realization of a FIFO queue as an adaptation of a SinglyLinkedList. 3 | */ 4 | public class LinkedQueue implements Queue { 5 | 6 | SinglyLinkedList list = new SinglyLinkedList<>(); 7 | 8 | @Override 9 | public int size() { 10 | return list.size(); 11 | } 12 | 13 | @Override 14 | public boolean isEmpty() { 15 | return list.isEmpty(); 16 | } 17 | 18 | @Override 19 | public void enqueue(E e) { 20 | list.addFirst(e); 21 | } 22 | 23 | @Override 24 | public E first() { 25 | return list.first(); 26 | } 27 | 28 | @Override 29 | public E dequeue() { 30 | return list.removeFirst(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch01/src/main/java/IsMultipleDemo.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | /** 4 | * R-1.3 Write a short Java method, isMultiple, that takes two long values, n and m, and returns true if and only if n 5 | * is a multiple of m, that is, n = mi for some integer i. 6 | */ 7 | public class IsMultipleDemo { 8 | public static void main(String[] args) { 9 | Scanner stdIn = new Scanner(System.in); 10 | System.out.println("Please input two numbers for n and m: "); 11 | long n = stdIn.nextLong(); 12 | long m = stdIn.nextLong(); 13 | System.out.println(isMultiple(n, m)); 14 | } 15 | 16 | private static boolean isMultiple(long n, long m) { 17 | if (m > n) { 18 | return isMultiple(m, n); 19 | } 20 | return n % m == 0; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch06/src/main/java/LinkedCircularQueue.java: -------------------------------------------------------------------------------- 1 | public class LinkedCircularQueue implements CircularQueue { 2 | 3 | CircularlyLinkedList list = new CircularlyLinkedList<>(); 4 | 5 | @Override 6 | public void rotate() { 7 | list.rotate(); 8 | } 9 | 10 | @Override 11 | public int size() { 12 | return list.size(); 13 | } 14 | 15 | @Override 16 | public boolean isEmpty() { 17 | return list.isEmpty(); 18 | } 19 | 20 | @Override 21 | public void enqueue(E e) throws IllegalStateException{ 22 | list.addFirst(e); 23 | } 24 | 25 | @Override 26 | public E first() { 27 | return list.first(); 28 | } 29 | 30 | @Override 31 | public E dequeue() { 32 | return list.removeFirst(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ch02/src/main/java/Photograph.java: -------------------------------------------------------------------------------- 1 | public class Photograph implements Sellable { 2 | 3 | private String descript; // description of this photo 4 | private int price; // the price we are setting 5 | private boolean color; // true if photo is in color 6 | 7 | public Photograph(String descript, int price, boolean color) { // constructor 8 | this.descript = descript; 9 | this.price = price; 10 | this.color = color; 11 | } 12 | 13 | @Override 14 | public String description() { 15 | return descript; 16 | } 17 | 18 | @Override 19 | public int listPrice() { 20 | return price; 21 | } 22 | 23 | @Override 24 | public int lowestPrice() { 25 | return price / 2; 26 | } 27 | 28 | public boolean isColor() { 29 | return color; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ch01/src/main/java/OnePointFive.java: -------------------------------------------------------------------------------- 1 | /** 2 | * R-1.5 Write a short Java method that takes an integer n and returns the sum of all positive integers less than or 3 | * equal to n. 4 | */ 5 | public class OnePointFive { 6 | public static void main(String[] args) { 7 | System.out.println(allSum(Integer.MAX_VALUE)); 8 | // System.out.println(sumOfPositive(Integer.MAX_VALUE)); 9 | } 10 | 11 | // 用 long 这样放 int 不会溢出,用高斯算法比较好。 12 | private static long allSum(long n) { 13 | 14 | if (n <= 0) { 15 | return 0; 16 | } 17 | return ((1 + n) * n) / 2; 18 | } 19 | 20 | // 这个算法有问题,因为 Integer.MAX_VALUE + 1 = -2147483648 <= n 所以死循环 21 | private static int sumOfPositive(int n) { 22 | int sum = 0; 23 | for (int i = 1; i <= n; i++) { 24 | sum = sum + i; 25 | } 26 | return sum; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch08/src/main/java/Tree.java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | 3 | /** 4 | * An interface for a tree where nodes can have an arbitrary number of children. 5 | */ 6 | public interface Tree extends Iterable { 7 | Position root(); 8 | 9 | Position parent(Position p) throws IllegalArgumentException; 10 | 11 | Iterable> children(Position p) throws IllegalArgumentException; 12 | 13 | int numChildren(Position p) throws IllegalArgumentException; 14 | 15 | boolean isInternal(Position p) throws IllegalArgumentException; 16 | 17 | boolean isExternal(Position p) throws IllegalArgumentException; 18 | 19 | boolean isRoot(Position p) throws IllegalArgumentException; 20 | 21 | int size(); 22 | 23 | boolean isEmpty(); 24 | 25 | @Override 26 | Iterator iterator(); 27 | 28 | Iterable> positions(); 29 | } 30 | -------------------------------------------------------------------------------- /ch07/src/main/java/Test.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Collections; 3 | import java.util.List; 4 | 5 | public class Test { 6 | public static void main(String[] args) { 7 | Integer[] numbers = {1, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 10}; 8 | List integers = Arrays.asList(numbers); 9 | int frequency = Collections.frequency(integers, 6); 10 | System.out.println(Collections.max(integers)); 11 | Collections.reverse(integers); 12 | System.out.println(frequency); 13 | System.out.println(integers); 14 | Collections.shuffle(integers); 15 | System.out.println(integers); 16 | Collections.sort(integers); 17 | System.out.println(integers); 18 | Integer[] number2 = integers.toArray(numbers); 19 | for (int a : number2) { 20 | System.out.print(a + " "); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 1. **[ch01](ch01/index.md)** Java Primer 2 | 3 | 2. **[ch02](ch02/index.md)** Object-Oriented Design 4 | 5 | 3. **[ch03](ch03/index.md)** Fundamental Data Structures 6 | 7 | 4. **[ch04](ch04/index.md)** Algorithm Analysis 8 | 9 | 5. **[ch05](ch05/index.md)** Recursion 10 | 11 | 6. **[ch06](ch06/index.md)** Stacks, Queues, and Deques 12 | 13 | 7. **[ch07](ch01/index.md)** List and Iterator ADTs 14 | 15 | 8. **[ch08](ch02/index.md)** Trees 16 | 17 | 9. **[ch09](ch03/index.md)** Priority Queues 18 | 19 | 10. **[ch10](ch04/index.md)** Maps, Hash Tables, and Skip Lists 20 | 21 | 11. **[ch11](ch05/index.md)** Search Trees 22 | 23 | 12. **[ch12](ch06/index.md)** Sorting and Selection 24 | 25 | 13. **[ch13](ch06/index.md)** Text Processing 26 | 27 | 14. **[ch14](ch06/index.md)** Graph Algorithms 28 | 29 | 15. **[ch15](ch06/index.md)** Memory Management and B-Trees 30 | -------------------------------------------------------------------------------- /ch08/src/main/java/BinaryTree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * An interface for a binary tree, in which each node has at most two children. 3 | * 4 | * @param element to operate on. 5 | */ 6 | public interface BinaryTree extends Tree { 7 | 8 | /** 9 | * @param p position in question 10 | * @return the Position of p's left child (or null if no child exists). 11 | * @throws IllegalArgumentException if something wrong. 12 | */ 13 | Position left(Position p) throws IllegalArgumentException; 14 | 15 | /** 16 | * @param p position in question 17 | * @return the Position of p's right child (or null if no child exists). 18 | * @throws IllegalArgumentException if something wrong. 19 | */ 20 | Position right(Position p) throws IllegalArgumentException; 21 | 22 | /** 23 | * @param p position in question 24 | * @return the Position of p's sibling (or null if no sibling exists). 25 | * @throws IllegalArgumentException if something wrong. 26 | */ 27 | Position sibling(Position p) throws IllegalArgumentException; 28 | } 29 | -------------------------------------------------------------------------------- /ch02/src/main/java/Student.java: -------------------------------------------------------------------------------- 1 | public class Student implements Person { 2 | 3 | String id; 4 | String name; 5 | int age; 6 | 7 | public Student(String id, String name, int age) { 8 | this.id = id; 9 | this.name = name; 10 | this.age = age; 11 | } 12 | 13 | protected int studyHours() { 14 | return age / 2; 15 | } 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | @Override 22 | public boolean equals(Person other) { 23 | if (!(other instanceof Student)) { 24 | return false; 25 | } 26 | Student s = (Student) other; 27 | return id.equals(s.id); 28 | } 29 | 30 | @Override 31 | public String getName() { 32 | return null; 33 | } 34 | 35 | @Override 36 | public int getAge() { 37 | return 0; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "Student{" + 43 | "ID='" + id + '\'' + 44 | ", Name='" + name + '\'' + 45 | ", Age=" + age + 46 | '}'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ch06/src/main/java/Stack.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Our own stack interface. 3 | * A collection of objects that are inserted and removed according to the last-in-first-out principle. 4 | * Although similar in purpose, this interface differs from java.util.Stack. 5 | * 6 | * @author tao 7 | */ 8 | public interface Stack { 9 | 10 | /** 11 | * Returns the numbers of elements in the stack. 12 | * @return number of elements in the stack. 13 | */ 14 | int size(); 15 | 16 | /** 17 | * Tests whether the stack is empty. 18 | * @return true if the stack is empty, false otherwise. 19 | */ 20 | boolean isEmpty(); 21 | 22 | /** 23 | * Inserts an element at the top of the stack. 24 | * @param e teh element to be inserted. 25 | */ 26 | void push(E e); 27 | 28 | /** 29 | * Returns, but does not remove, the element at teh top of the stack. 30 | * @return top element in the stack (or null if empty). 31 | */ 32 | E top(); 33 | 34 | /** 35 | * Removes and returns the top element from the stack. 36 | * @return element removed (or null if empty). 37 | */ 38 | E pop(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /ch01/src/main/java/IsEvenDemo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * R-1.4 Write a short Java method, isEven, that takes an int i and returns true if and only if i is even. Your method 3 | * cannot user the multiplication, modulus, or division operators, however. 4 | */ 5 | public class IsEvenDemo { 6 | 7 | public static void main(String[] args) { 8 | System.out.println(isEven(19381)); 9 | } 10 | 11 | private static boolean isEven(int n) { 12 | // use a loop to decrease the value of i by 2 at each iteration 13 | // if value of i reaches zero at any iteration before becoming negative, 14 | // then it is even 15 | // Ex: int i = 5; 16 | // when iteration = 1, i = 5-2 = 3 (not zero) 17 | // when iteration = 2, i = 3-2 = 1 (not zero) 18 | // when iteration = 3, i = 1-2 = -1 (negative), comes out of loop 19 | // Similarly, when int i = 4; 20 | // when iteration = 1, i = 4-2 = 2 (not zero) 21 | // when iteration = 2, i = 2-2 = 0 (even) 22 | while (n > 0) { 23 | n = n - 2; 24 | if (n == 0) { 25 | return true; 26 | } 27 | } 28 | return false; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ch03/src/main/java/InsertionSort.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | /** 4 | * Insertion-sort of an array of characters into nondecreasing order 5 | */ 6 | public class InsertionSort { 7 | 8 | public static void main(String[] args) { 9 | char[] letters = {'B', 'C', 'D', 'A', 'E', 'H', 'G', 'F'}; 10 | char[] others = new char[5]; 11 | Arrays.fill(others, 'a'); 12 | System.out.println(others); 13 | System.out.println(letters); 14 | // insertionSort(letters); 15 | Arrays.sort(letters); 16 | System.out.println(letters); 17 | } 18 | 19 | public static void insertionSort(char[] data) { 20 | int n = data.length; 21 | for (int k = 1; k < n; k++) { // begin with second character 22 | char cur = data[k]; // time to insert cur = data[k] 23 | int j = k; // find correct index j for cur 24 | while (j > 0 && data[j - 1] > cur) { // thus, data[j-1] must go after cur 25 | data[j] = data[j - 1]; // slide data[j-1] rightward 26 | j--; // and consider previous j for cur 27 | } 28 | data[j] = cur; // this is the proper place for cur 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ch02/src/main/java/BoxedItem.java: -------------------------------------------------------------------------------- 1 | public class BoxedItem implements Sellable, Transportable{ 2 | 3 | private String descript; 4 | private int price; 5 | private int weight; 6 | private boolean haz; 7 | private int height = 0; 8 | private int width = 0; 9 | private int depth = 0; 10 | 11 | public BoxedItem(String descript, int price, int weight, boolean haz) { 12 | this.descript = descript; 13 | this.price = price; 14 | this.weight = weight; 15 | this.haz = haz; 16 | } 17 | 18 | @Override 19 | public String description() { 20 | return descript; 21 | } 22 | 23 | @Override 24 | public int listPrice() { 25 | return price; 26 | } 27 | 28 | @Override 29 | public int lowestPrice() { 30 | return price / 2; 31 | } 32 | 33 | @Override 34 | public int weight() { 35 | return weight; 36 | } 37 | 38 | @Override 39 | public boolean isHazardous() { 40 | return haz; 41 | } 42 | 43 | public int insuredValue() { 44 | return price * 2; 45 | } 46 | 47 | public void setBox(int height, int width, int depth) { 48 | this.height = height; 49 | this.width = width; 50 | this.depth = depth; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ch02/src/main/java/Progression.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Generate a simple progression. By default: 0, 1, 2, ... 3 | */ 4 | public class Progression { 5 | 6 | // instance variable 7 | protected long current; 8 | 9 | /** Constructs a progression starting at zero. */ 10 | public Progression() { this(0); } 11 | 12 | /** Constructs a progression with given start value. */ 13 | public Progression(long start) { this.current = start; } 14 | 15 | /** Returns the next value of the progression. */ 16 | public long nextValue() { 17 | long answer = current; 18 | advance(); // this protected call is responsible for advancing the current value 19 | return answer; 20 | } 21 | 22 | /** Advances the current value to the next value of the progression. */ 23 | protected void advance() { 24 | current++; 25 | } 26 | 27 | /** Prints the next n values of the progression, separated by spaces. */ 28 | public void printProgression(int n) { 29 | System.out.print(nextValue()); // print first value without leading space. 30 | for (int j = 1; j < n; j++) { 31 | System.out.print(" " + nextValue()); // print leading space before others 32 | } 33 | System.out.println(); // end the line 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch02/src/main/java/BoxedItem2.java: -------------------------------------------------------------------------------- 1 | public class BoxedItem2 implements Insurable { 2 | 3 | private String descript; 4 | private int price; 5 | private int weight; 6 | private boolean haz; 7 | private int height = 0; 8 | private int width = 0; 9 | private int depth = 0; 10 | 11 | public BoxedItem2(String descript, int price, int weight, boolean haz) { 12 | this.descript = descript; 13 | this.price = price; 14 | this.weight = weight; 15 | this.haz = haz; 16 | } 17 | 18 | @Override 19 | public String description() { 20 | return descript; 21 | } 22 | 23 | @Override 24 | public int listPrice() { 25 | return price; 26 | } 27 | 28 | @Override 29 | public int lowestPrice() { 30 | return price / 2; 31 | } 32 | 33 | @Override 34 | public int weight() { 35 | return weight; 36 | } 37 | 38 | @Override 39 | public boolean isHazardous() { 40 | return haz; 41 | } 42 | 43 | @Override 44 | public int insuredValue() { 45 | return price * 2; 46 | } 47 | 48 | public void setBox(int height, int width, int depth) { 49 | this.height = height; 50 | this.width = width; 51 | this.depth = depth; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ch04/src/main/java/StringConcat.java: -------------------------------------------------------------------------------- 1 | import java.util.concurrent.ExecutorService; 2 | import java.util.concurrent.Executors; 3 | 4 | public class StringConcat { 5 | /** 6 | * Uses repeated concatenation to compose a String with n copies of character c. 7 | */ 8 | public static String repeat1(char c, int n) { 9 | String answer = ""; 10 | for (int j = 0; j < n; j++) 11 | answer += c; 12 | return answer; 13 | } 14 | 15 | /** 16 | * Uses StringBuilder to compose a String with n copies of character c. 17 | */ 18 | public static String repeat2(char c, int n) { 19 | StringBuilder sb = new StringBuilder(); 20 | for (int j = 0; j < n; j++) { 21 | sb.append(c); 22 | } 23 | return sb.toString(); 24 | } 25 | 26 | public static void main(String[] args) { 27 | Runnable task1 = () -> { 28 | System.out.println(repeat1('*', 100)); 29 | }; 30 | 31 | Runnable task2 = () -> { 32 | System.out.println(repeat2('*', 100)); 33 | }; 34 | 35 | ExecutorService service = Executors.newSingleThreadExecutor(); 36 | service.execute(task1); 37 | service.execute(task2); 38 | 39 | service.shutdown(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /ch04/src/main/java/PrefixAverage.java: -------------------------------------------------------------------------------- 1 | public class PrefixAverage { 2 | 3 | /** 4 | * Returns an array a such that, for all j, a[j] equals the average of x[0],...,x[j]. 5 | */ 6 | public static double[] prefixAverage1(double[] x) { 7 | int n = x.length; 8 | double[] a = new double[n]; // filled with zeros by default 9 | for (int j = 0; j < n; j++) { 10 | double total = 0; // begin computing x[0] + ... + x[j] 11 | for (int i = 0; i <= j; i++) 12 | total += x[i]; 13 | a[j] = total / (j + 1); // record the average 14 | } 15 | return a; 16 | } 17 | 18 | /** 19 | * Returns an array a such that, for all j, a[j] equals the average of x[0],...,x[j]. 20 | * 21 | * @param x 要统计的数据 22 | * @return 已经计算好的结果 23 | */ 24 | public static double[] prefixAverage2(double[] x) { 25 | int n = x.length; 26 | double[] a = new double[n]; // filled with zeros by default 27 | double total = 0; // compute prefix sum as x[0] + x[1] + ... 28 | for (int j = 0; j < n; j++) { 29 | total += x[j]; // update prefix sum to include x[j] 30 | a[j] = total / (j + 1); // compute average based on current sum 31 | } 32 | return a; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ch14/src/main/java/Edge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | /** 25 | * An edge of a graph. 26 | * 27 | * @author Michael T. Goodrich 28 | * @author Roberto Tamassia 29 | * @author Michael H. Goldwasser 30 | */ 31 | public interface Edge { 32 | /** Returns the element associated with the edge. */ 33 | E getElement(); 34 | } 35 | -------------------------------------------------------------------------------- /ch14/src/main/java/Vertex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | /** 25 | * A vertex of a graph. 26 | * 27 | * @author Michael T. Goodrich 28 | * @author Roberto Tamassia 29 | * @author Michael H. Goldwasser 30 | */ 31 | public interface Vertex { 32 | /** Returns the element associated with the vertex. */ 33 | V getElement(); 34 | } 35 | -------------------------------------------------------------------------------- /ch10/src/main/java/WordCount.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | /** 4 | * A program that counts words in a document, printing the most frequent. 5 | */ 6 | public class WordCount { 7 | public static void main(String[] args) { 8 | Map freq = new ChainHashMap<>(); // or any concrete map 9 | // scan input for words, using all nonletters as delimiters 10 | Scanner doc = new Scanner(System.in).useDelimiter("[^a-zA-Z]+"); 11 | while (doc.hasNext()) { 12 | String word = doc.next().toLowerCase(); // convert next word to lowercase 13 | Integer count = freq.get(word); // get the previous count for this word 14 | if (count == null) 15 | count = 0; // if not in map, previous count is zero 16 | freq.put(word, 1 + count); // (re)assign new count for this word 17 | } 18 | int maxCount = 0; 19 | String maxWord = "no word"; 20 | for (Entry ent : freq.entrySet()) // find max-count word 21 | if (ent.getValue() > maxCount) { 22 | maxWord = ent.getKey(); 23 | maxCount = ent.getValue(); 24 | } 25 | System.out.println("The most frequent word is '" + maxWord); 26 | System.out.println("' with " + maxCount + " occurrences."); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch01/src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | import java.util.Scanner; 4 | 5 | /** 6 | * R-1.1 7 | * Write a short Java method, inputAllBaseTypes, that inputs a different value of each base type from the standard input 8 | * device and prints it back to the standard output device. 9 | */ 10 | public class Main { 11 | public static void main(String[] args) { 12 | inputAllBaseTypes(); 13 | } 14 | 15 | private static void inputAllBaseTypes() { 16 | Scanner stdIn = new Scanner(System.in); 17 | List list = new ArrayList<>(); 18 | // basic types: int, short, long, char, byte, boolean, float, double 19 | short aShort = stdIn.nextShort(); 20 | int anInt = stdIn.nextInt(); 21 | long aLong = stdIn.nextLong(); 22 | char aChar = stdIn.next().charAt(0); 23 | byte aByte = stdIn.nextByte(); 24 | boolean aBoolean = stdIn.nextBoolean(); 25 | float aFloat = stdIn.nextFloat(); 26 | double aDouble = stdIn.nextDouble(); 27 | 28 | list.add(aShort); 29 | list.add(anInt); 30 | list.add(aLong); 31 | list.add(aChar); 32 | list.add(aByte); 33 | list.add(aBoolean); 34 | list.add(aFloat); 35 | list.add(aDouble); 36 | 37 | System.out.println(list); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ch07/src/main/java/SortingPositionalList.java: -------------------------------------------------------------------------------- 1 | public class SortingPositionalList { 2 | 3 | public static void insertionSort(PositionalList list) { 4 | Position marker = list.first(); // last position known to be sorted 5 | while (marker != list.last()) { 6 | Position pivot = list.after(marker); 7 | int value = pivot.getElement(); 8 | if (value > marker.getElement()) 9 | marker = pivot; 10 | else { 11 | Position walk = marker; 12 | while (walk != list.first() && list.before(walk).getElement() > value) 13 | walk = list.before(walk); 14 | list.remove(pivot); // remove pivot entry and 15 | list.addBefore(walk, value); // reinsert value in front of walk 16 | } 17 | } 18 | } 19 | 20 | public static void main(String[] args) { 21 | LinkedPositionalList list = new LinkedPositionalList<>(); 22 | Position first = list.addFirst(1); 23 | Position second = list.addAfter(first, 4); 24 | list.addAfter(second, 0); 25 | list.addBefore(first, 20); 26 | insertionSort(list); 27 | for (Integer thing : list) { 28 | System.out.println(thing); 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /ch10/src/main/java/CostPerformanceDatabase.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Maintains a database of maximal (cost, performance) pairs. 3 | */ 4 | public class CostPerformanceDatabase { 5 | 6 | SortedMap map = new SortedTableMap<>(); 7 | 8 | /** 9 | * Constructs an initially empty database. 10 | */ 11 | public CostPerformanceDatabase() {} 12 | 13 | /** 14 | * Returns the (cost, performance) entry with largest cost not exceeding c. 15 | * (or null if no entry exist with cost c or less). 16 | */ 17 | public Entry best(int cost) { 18 | return map.floorEntry(cost); 19 | } 20 | 21 | /** 22 | * Add a new entry with given cost c and performance p. 23 | */ 24 | public void add(int c, int p) { 25 | Entry other = map.floorEntry(c); // other is at least as cheap 26 | if (other != null && other.getValue() >= p) // if its performance is as good 27 | return; 28 | map.put(c, p); // else, add (c,p) to database 29 | // and now remove any entries that are dominated by the new one 30 | other = map.higherEntry(c); // other is more expensive than c 31 | while (other != null && other.getValue() <= p) { // if not better performance 32 | map.remove(other.getKey()); // remove the other entry 33 | other = map.higherEntry(c); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch02/src/main/java/TestProgression.java: -------------------------------------------------------------------------------- 1 | public class TestProgression { 2 | public static void main(String[] args) { 3 | Progression prog; 4 | 5 | // test ArithmeticProgression 6 | System.out.print("Arithmetic progression with default increment: "); 7 | prog = new ArithmeticProgression(); 8 | prog.printProgression(10); 9 | System.out.print("Arithmetic progression with increment 5: "); 10 | prog = new ArithmeticProgression(5); 11 | prog.printProgression(10); 12 | System.out.print("Arithmetic progression with start 2: "); 13 | prog = new ArithmeticProgression(5, 2); 14 | prog.printProgression(10); 15 | // test GeometricProgression 16 | System.out.print("Geometric progression with default base: "); 17 | prog = new GeometricProgression(); 18 | prog.printProgression(10); 19 | System.out.print("Geometric progression with base 3: "); 20 | prog = new GeometricProgression(3); 21 | prog.printProgression(10); 22 | // test FibonacciProgression 23 | System.out.print("Fibonacci progression with default start values: "); 24 | prog = new FibonacciProgression(); 25 | prog.printProgression(10); 26 | System.out.print("Fibonacci progression with start values 4 and 6: "); 27 | prog = new FibonacciProgression(4, 6); 28 | prog.printProgression(8); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ch06/src/main/java/ArrayStack.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 基于数组实现的栈 3 | */ 4 | public class ArrayStack implements Stack { 5 | 6 | public static final int CAPACITY = 1000; // default array capacity. 默认数组容量 7 | private E[] data; // generic array used for storage. 8 | private int t = -1; // index of the top element in stack. 9 | public ArrayStack() { // constructs stack with default capacity. 10 | this(CAPACITY); 11 | } 12 | 13 | public ArrayStack(int capacity) { // constructs stack with given capacity. 14 | data = (E[]) new Object[capacity]; // safe cast; compiler may give warning. 15 | } 16 | 17 | @Override 18 | public int size() { 19 | return t + 1; 20 | } 21 | 22 | @Override 23 | public boolean isEmpty() { 24 | return (t == -1); 25 | } 26 | 27 | @Override 28 | public void push(E e) throws IllegalStateException { 29 | if (size() == data.length) throw new IllegalStateException("Stack is full"); 30 | data[++t] = e; // increment t before storing new item. 31 | } 32 | 33 | @Override 34 | public E top() { 35 | if (isEmpty()) return null; 36 | return data[t]; 37 | } 38 | 39 | @Override 40 | public E pop() { 41 | if (isEmpty()) return null; 42 | E answer = data[t]; 43 | data[t] = null; // dereference to help garbage collection. 44 | t--; 45 | return answer; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ch06/src/main/java/StackUsageDemo.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.List; 3 | 4 | public class StackUsageDemo { 5 | 6 | public static void reverse(E[] a) { 7 | Stack buffer = new ArrayStack<>(a.length); 8 | for (E e : a) buffer.push(e); 9 | for (int i = 0; i < a.length; i++) 10 | a[i] = buffer.pop(); 11 | } 12 | 13 | public static void main(String[] args) { 14 | String letters = "ABCDEFG"; 15 | char[] chars = letters.toCharArray(); 16 | Character[] characters = new Character[letters.length()]; 17 | for (int i = 0; i < letters.length(); i++) { 18 | characters[i] = chars[i]; 19 | } 20 | List characters1 = Arrays.asList(characters); 21 | System.out.println(Arrays.toString(chars)); 22 | System.out.println("Reversing..."); 23 | reverse(characters); 24 | System.out.println(characters1); 25 | 26 | Integer[] a = {4, 8, 15, 16, 23, 42}; // autoboxing allows this. 27 | String[] s = {"Jack", "Kate", "Hurley", "Jin", "Michael"}; 28 | System.out.println("a = " + Arrays.toString(a)); 29 | System.out.println("s = " + Arrays.toString(s)); 30 | System.out.println("Reversing..."); 31 | reverse(a); 32 | reverse(s); 33 | System.out.println("a = " + Arrays.toString(a)); 34 | System.out.println("s = " + Arrays.toString(s)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch05/src/main/java/EnglishRuler.java: -------------------------------------------------------------------------------- 1 | public class EnglishRuler { 2 | /** 3 | * Draws an English ruler for the given number of inches and major tick length. 4 | */ 5 | public static void drawRuler(int nInches, int majorLength) { 6 | drawLine(majorLength, 0); // draw inch 0 line and label 7 | for (int j = 1; j <= nInches; j++) { 8 | drawInterval(majorLength - 1); // draw interior ticks for inch 9 | drawLine(majorLength, j); // draw inch j line and label 10 | } 11 | } 12 | 13 | private static void drawInterval(int centralLength) { 14 | if (centralLength >= 1) { // otherwise, do nothing 15 | drawInterval(centralLength - 1); // recursively draw top interval 16 | drawLine(centralLength); // draw center tick line (without label) 17 | drawInterval(centralLength - 1); // recursively draw bottom interval 18 | } 19 | } 20 | 21 | private static void drawLine(int tickLength, int tickLabel) { 22 | for (int j = 0; j < tickLength; j++) 23 | System.out.print("-"); 24 | if (tickLabel >= 0) 25 | System.out.print(" " + tickLabel); 26 | System.out.print("\n"); 27 | } 28 | 29 | /** 30 | * Draws a line with the given tick length (but no label). 31 | */ 32 | private static void drawLine(int tickLength) { 33 | drawLine(tickLength, -1); 34 | } 35 | 36 | public static void main(String[] args) { 37 | drawRuler(3, 3); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ch07/src/main/java/List.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A simplified version of the java.util.List interface. 3 | * @param 元素 4 | */ 5 | public interface List { 6 | 7 | /** 8 | * 9 | * @return the number of 10 | */ 11 | int size(); 12 | 13 | /** 14 | * Returns whether the list is empty. 15 | */ 16 | boolean isEmpty(); 17 | 18 | /** 19 | * 20 | * @param i index 21 | * @return Returns (but does not remove) the element at index i. 22 | * @throws IndexOutOfBoundsException exception 23 | */ 24 | E get(int i) throws IndexOutOfBoundsException; 25 | 26 | /** 27 | * Replaces the element at index i with e, and returns the replaced element. 28 | * @param i index 29 | * @param e the new element 30 | * @return the replaced element. 31 | * @throws IndexOutOfBoundsException exception 32 | */ 33 | E set(int i, E e) throws IndexOutOfBoundsException; 34 | 35 | /** 36 | * Inserts element e to be at index i, shifting all subsequent element later. 37 | * @param i index 38 | * @param e the element to be added 39 | * @throws IndexOutOfBoundsException exception 40 | */ 41 | void add(int i, E e) throws IndexOutOfBoundsException; 42 | 43 | 44 | /** 45 | * Removes/returns the element at index i, shifting subsequent elements earlier. 46 | * @param i index 47 | * @return the removed element 48 | * @throws IndexOutOfBoundsException exception 49 | */ 50 | E remove(int i) throws IndexOutOfBoundsException; 51 | } 52 | -------------------------------------------------------------------------------- /ch09/src/main/java/SortedPriorityQueue.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | /** 4 | * An implementation of a priority queue with a sorted list. 5 | */ 6 | public class SortedPriorityQueue extends AbstractPriorityQueue { 7 | 8 | /** 9 | * primary collection of priority queue entries. 10 | */ 11 | private PositionalList> list = new LinkedPositionalList<>(); 12 | 13 | /** 14 | * Creates an empty priority queue based on the natural ordering of its keys. 15 | */ 16 | public SortedPriorityQueue() { 17 | super(); 18 | } 19 | 20 | /** 21 | * Creates an empty priority queue using the given comparator to order keys. 22 | */ 23 | public SortedPriorityQueue(Comparator comp) { 24 | super(comp); 25 | } 26 | 27 | /** 28 | * Returns the number of items in the priority queue. 29 | */ 30 | @Override 31 | public int size() { 32 | return list.size(); 33 | } 34 | 35 | /** 36 | * Inserts a key-value pair and returns the entry created. 37 | */ 38 | @Override 39 | public Entry insert(K key, V value) throws IllegalArgumentException { 40 | return null; 41 | } 42 | 43 | /** 44 | * Returns (but does not remove) an entry with minimal key. 45 | */ 46 | @Override 47 | public Entry min() { 48 | return null; 49 | } 50 | 51 | /** 52 | * Removes and returns an entry with minimal key. 53 | */ 54 | @Override 55 | public Entry removeMin() { 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ch06/src/main/java/Deque.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 双端队列 ADT 3 | * 4 | * @param 元素 5 | * Interface for a double-ended queue. a collection of elements that can be inserted and removed at both ends; 6 | * this interface is a simplified version of java.util.Deque. 7 | */ 8 | public interface Deque { 9 | /** 10 | * @return the number of elements in the deque. 11 | */ 12 | int size(); 13 | 14 | /** 15 | * @return Tests whether the deque is empty. 16 | */ 17 | boolean isEmpty(); 18 | 19 | /** 20 | * @return Returns, but does not remove, the first element of the deque (null if empty). 21 | */ 22 | E first(); 23 | 24 | /** 25 | * Returns, but does not remove, the last element of the deque (null if empty). 26 | * 27 | * @return last element of the deque. 28 | */ 29 | E last(); 30 | 31 | /** 32 | * Inserts an element at the front of the deque. 33 | * 34 | * @param e the element to be inserted at the front. 35 | */ 36 | void addFirst(E e); 37 | 38 | /** 39 | * Inserts an element at the back of the deque. 40 | * 41 | * @param e the element to be added. 42 | */ 43 | void addLast(E e); 44 | 45 | /** 46 | * Removes and returns the first element in the deque (null if empty). 47 | * 48 | * @return the first element. 49 | */ 50 | E removeFirst(); 51 | 52 | /** 53 | * Removes and returns the last element of the deque (null if empty). 54 | * 55 | * @return the last element. 56 | */ 57 | E removeLast(); 58 | } 59 | -------------------------------------------------------------------------------- /ch06/src/main/java/JosephusProblem.java: -------------------------------------------------------------------------------- 1 | public class JosephusProblem { 2 | /** 3 | * Computes the winner of the Josephus problem using a circular queue. 4 | * 5 | * @param queue 6 | * @param k 7 | * @param 8 | * @return 9 | */ 10 | public static E Josephus(CircularQueue queue, int k) { 11 | if (queue.isEmpty()) return null; 12 | while (queue.size() > 1) { 13 | for (int i = 0; i < k - 1; i++) // skip past k-1 elements 14 | queue.rotate(); 15 | E e = queue.dequeue(); // remove the front element from the collection 16 | System.out.println(" " + e + " is out"); 17 | } 18 | return queue.dequeue(); // the winner 19 | } 20 | 21 | /** 22 | * Builds a circular queue from an array of objects. 23 | */ 24 | public static CircularQueue buildQueue(E a[]) { 25 | CircularQueue queue = new LinkedCircularQueue<>(); 26 | for (int i = 0; i < a.length; i++) 27 | queue.enqueue(a[i]); 28 | return queue; 29 | } 30 | 31 | /** 32 | * Tester method 33 | */ 34 | public static void main(String[] args) { 35 | String[] a1 = {"Alice", "Bob", "Cindy", "Doug", "Ed", "Fred"}; 36 | String[] a2 = {"Gene", "Hope", "Irene", "Jack", "Kim", "Lance"}; 37 | String[] a3 = {"Mike", "Roberto"}; 38 | System.out.println("First winner is " + Josephus(buildQueue(a1), 6)); 39 | System.out.println("Second winner is " + Josephus(buildQueue(a2), 120)); 40 | System.out.println("Third winner is " + Josephus(buildQueue(a3), 7)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ch06/src/main/java/ArrayQueue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of the queue ADT using a fixed-length array. 3 | */ 4 | public class ArrayQueue implements Queue { 5 | 6 | public static final int CAPACITY = 1000; 7 | 8 | 9 | // instance variables 10 | private E[] data; // generic array used for storage 11 | private int f = 0; // index of the front element 12 | private int sz = 0; // current number of elements 13 | 14 | // constructors 15 | public ArrayQueue() { // constructs queue with default capacity. 16 | this(CAPACITY); 17 | } 18 | 19 | public ArrayQueue(int capacity) { // constructs queue with given capacity. 20 | data = (E[]) new Object[capacity]; // safe cast; compile may give warning. 21 | } 22 | 23 | @Override 24 | public int size() { 25 | return sz; 26 | } 27 | 28 | @Override 29 | public boolean isEmpty() { 30 | return (sz == 0); 31 | } 32 | 33 | /** 34 | * Inserts an element at the rear of the queue. 35 | */ 36 | @Override 37 | public void enqueue(E e) throws IllegalStateException { 38 | if (sz == data.length) throw new IllegalStateException("Queue is full"); 39 | int avail = (f + sz) % data.length; // use modular arithmetic 40 | data[avail] = e; 41 | sz++; 42 | } 43 | 44 | @Override 45 | public E first() { 46 | if (isEmpty()) return null; 47 | return data[f]; 48 | } 49 | 50 | @Override 51 | public E dequeue() { 52 | if (isEmpty()) return null; 53 | E answer = data[f]; 54 | data[f] = null; 55 | f = (f + 1) % data.length; 56 | sz++; 57 | return answer; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ch01/src/main/java/OnePointSix.java: -------------------------------------------------------------------------------- 1 | /** 2 | * R-1.6 Write a short Java method that takes an integer n and returns the sum of all the odd positive integers less 3 | * than or equal to n. 4 | * 其实就是等差数列求前 n 项和的问题。 5 | */ 6 | public class OnePointSix { 7 | 8 | public static void main(String[] args) throws Exception { 9 | System.out.println(sumOfOddPositive(8L)); 10 | System.out.println(sumOfOddPositive(8)); 11 | } 12 | 13 | private static long sumOfOddPositive(long n) throws IllegalArgumentException { 14 | // 先判断奇偶,偶数则 / 2 得到项数, 奇数则 - 1 再 / 2 得到项数 15 | // 之后就套用等差数列前 n 项和公式即可。 16 | if (n < 0) { 17 | throw new IllegalArgumentException("不能小于零"); 18 | } 19 | long terms = n % 2 == 0 ? n / 2 : (n - 1) / 2; 20 | return terms * (2 + (terms - 1) * 2) / 2; 21 | } 22 | 23 | // method to add all odd positive integers till n 24 | // 这个傻狗算法,竟然出现在答案网站,看起来那个网站的答案不是书本官方的配套,是网页贡献的。 25 | // 这个也是会因为溢出而死循环,比较傻的是不用等差数列。 26 | private static int sumOfOddPositive(int n){ 27 | // Variable to store the sum of odd positive integers (initialized with 0) 28 | int sum = 0; 29 | // use a loop to add all the odd positive integers till n, iteratively 30 | // in the variable sum 31 | // iterate using steps of 2 to take only odd elements 32 | // Ex: int n = 8; 33 | // when i = 1, sum = 0+1 = 1 34 | // when i = 3, sum = 1+3 = 4 35 | // when i = 5, sum = 4+5 = 9 36 | // when i = 7, sum = 9+7 = 16 37 | for(int i = 1; i <= n; i=i+2){ 38 | sum = sum+i; 39 | } 40 | // return the sum of all odd positive integers till n 41 | // ex: when n = 8, return 15 42 | return sum; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ch07/src/main/java/FavoritesListMTF.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Maintains a list of elements ordered with move-to-front heuristic. 3 | */ 4 | public class FavoritesListMTF extends FavoritesList { 5 | 6 | /** 7 | * Moves accessed item at Position p to the front of the list. 8 | * 9 | * @param p position to be moved 10 | */ 11 | @Override 12 | protected void moveUp(Position> p) { 13 | if (p != list.first()) 14 | list.addFirst(list.remove(p)); // remove/reinsert item 15 | } 16 | 17 | /** 18 | * @param k frequency 19 | * @return an iterable collection of the k most frequently accessed elements. 20 | * @throws IllegalArgumentException if goes wrong. 21 | */ 22 | @Override 23 | public Iterable getFavorites(int k) throws IllegalArgumentException { 24 | if (k < 0 || k > size()) 25 | throw new IllegalArgumentException("Invalid k"); 26 | 27 | // we begin by making a copy of the original list 28 | PositionalList> temp = new LinkedPositionalList<>(); 29 | for (Item item : list) 30 | temp.addLast(item); 31 | 32 | PositionalList result = new LinkedPositionalList<>(); 33 | for (int j = 0; j < k; j++) { 34 | Position> highPos = temp.first(); 35 | Position> walk = temp.after(highPos); 36 | while (walk != null) { 37 | if (count(walk) > count(highPos)) 38 | highPos = walk; 39 | walk = temp.after(walk); 40 | } 41 | // we have now found element with highest count 42 | result.addLast(value(highPos)); 43 | temp.remove(highPos); 44 | } 45 | return result; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /ch03/src/main/java/ScoreBoard.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Class for storing high scores in an array in nondecreasing order. 3 | */ 4 | public class ScoreBoard { 5 | private int numEntries = 0; 6 | private GameEntry[] board; 7 | 8 | /** 9 | * Constructs an empty scoreboard with the given capacity for storing entries. 10 | */ 11 | public ScoreBoard(int capacity) { 12 | board = new GameEntry[capacity]; 13 | } 14 | 15 | /** 16 | * Attempt to add a new score to the collection (if it is high enough) 17 | * 18 | * @param e the GameEntry to add 19 | */ 20 | public void add(GameEntry e) { 21 | int newScore = e.getScore(); 22 | // 如果有空间放得下,或者新的分数高于板上最低分数 23 | if (numEntries < board.length || newScore > board[numEntries - 1].getScore()) { 24 | if (numEntries < board.length) { 25 | numEntries++; 26 | } 27 | int j = numEntries - 1; 28 | while (j > 0 && board[j - 1].getScore() < newScore) { 29 | board[j] = board[j - 1]; 30 | j--; 31 | } 32 | board[j] = e; 33 | } 34 | } 35 | 36 | /*** 37 | * Remove and return the high score at index 38 | */ 39 | public GameEntry remove(int i) throws IndexOutOfBoundsException { 40 | if (i < 0 || i >= numEntries) { 41 | throw new IndexOutOfBoundsException("Invalid index: " + i); 42 | } 43 | GameEntry temp = board[i]; 44 | // if (numEntries - 1 - i >= 0) System.arraycopy(board, i + 1, board, i, numEntries - 1 - i); 45 | for (int j = i; j < numEntries - 1; j++) { 46 | board[j] = board[j + 1]; 47 | } 48 | board[numEntries - 1] = null; 49 | numEntries--; 50 | return temp; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ch02/src/main/java/PredatoryCreditCard.java: -------------------------------------------------------------------------------- 1 | public class PredatoryCreditCard extends CreditCard{ 2 | 3 | // Additional instance variable 4 | private double apr; // annual percentage rate 5 | // private double balance; 不能够这样,会 knock out super 的 balance 6 | 7 | // 构造函数不会被继承 8 | 9 | public PredatoryCreditCard(String customer, String bank, String account, int limit, double initialBalance, double apr) { 10 | super(customer, bank, account, limit, initialBalance); 11 | this.apr = apr; 12 | } 13 | 14 | // A new method for assessing monthly interest charges 15 | public void processMonth() { 16 | if (balance > 0) { // only charge interest on a positive balance 17 | // 注意这里计算 monthly rate 的方式是 1 + apr 之后开 12 次方根 18 | // We do not simply divide the annual rate by twelve to get a monthly rate (that would be too predatory, as 19 | // it would result in a higher APR than advertised). 20 | double monthlyFactor = Math.pow(1 + apr, 1.0 / 12); // 正确的复利计算 21 | balance *= monthlyFactor; 22 | } 23 | } 24 | 25 | // Overriding the charge method defined in the superclass 26 | @Override 27 | public boolean charge(double price) { 28 | boolean isSuccess = super.charge(price); 29 | if (!isSuccess) { 30 | balance += 5; 31 | //charge(5); 32 | } 33 | return isSuccess; 34 | } 35 | 36 | public static void main(String[] args) { 37 | PredatoryCreditCard creditCard = new PredatoryCreditCard( 38 | "John Bowman", 39 | "California Finance", 40 | "5391 0375 9387 5309", 41 | 2500, 42 | 300, 43 | 0.02); 44 | System.out.println(creditCard.getAccount()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ch01/src/main/java/CloneDemo.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Random; 3 | 4 | /** 5 | * R-1.2 Suppose that we create an array A of GameEntry objects, which has an integer scores field, and we clone A and 6 | * store the result in an array B. If we then immediately set A[4].score equal to 500, what is the score value of the 7 | * GameEntry object referenced by B[4]? 8 | */ 9 | public class CloneDemo { 10 | public static void main(String[] args) { 11 | 12 | GameEntry[] A = new GameEntry[5]; 13 | for (int i = 0; i < A.length; i++) { 14 | A[i] = new GameEntry(new Random().nextInt(500) + 1); 15 | } 16 | GameEntry[] B = A.clone(); 17 | System.out.println("A contents below"); 18 | printScores(A); 19 | System.out.println("\n++++++++++++++++++++++++++"); 20 | System.out.println("B contents below"); 21 | printScores(B); 22 | System.out.println("set A[4] to 550"); 23 | A[4].setScore(550); 24 | System.out.println("print B[4]"); 25 | System.out.println(B[4].getScore()); 26 | System.out.println(A.equals(B)); // false 27 | System.out.println(Arrays.equals(A, B)); // true 28 | System.out.println(A[4].equals(B[4])); // true 29 | // 结论是 clone() 之后,数组 A 和 数组 B 是不同的对象,但是里边对应 index 存的 GameEntry 却同样的。 30 | } 31 | 32 | private static void printScores(GameEntry[] a) { 33 | for (GameEntry gameEntry : a) { 34 | System.out.print(gameEntry.getScore() + " "); 35 | } 36 | System.out.println(); 37 | } 38 | } 39 | 40 | class GameEntry { 41 | private Integer score; 42 | 43 | GameEntry(Integer score) { 44 | this.score = score; 45 | } 46 | 47 | public Integer getScore() { 48 | return score; 49 | } 50 | 51 | public void setScore(Integer score) { 52 | this.score = score; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ch13/src/main/java/MatrixChain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | public class MatrixChain { 25 | /** 26 | * Returns an n-by-n matrix such that N[i][j] represents the minimum number of 27 | * multiplications to compute the product of matrix chain product Ai through Aj inclusive. 28 | * 29 | * The parameter d is an array of n+1 numbers, such that the size of the kth 30 | * matrix is d[k]-by-d[k+1]. 31 | */ 32 | public static int[][] matrixChain(int[] d) { 33 | int n = d.length - 1; // number of matrices 34 | int[][] N = new int[n][n]; // n-by-n matrix; initially zeros 35 | for (int b=1; b < n; b++) // number of products in subchain 36 | for (int i=0; i < n - b; i++) { // start of subchain 37 | int j = i + b; // end of subchain 38 | N[i][j] = Integer.MAX_VALUE; // used as 'infinity' 39 | for (int k=i; k < j; k++) 40 | N[i][j] = Math.min(N[i][j], N[i][k] + N[k+1][j] + d[i]*d[k+1]*d[j+1]); 41 | } 42 | return N; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/ch01/index.md: -------------------------------------------------------------------------------- 1 | # 1.10 Exercises 2 | ### Reinforcement 3 | **R-1.1** Write a short Java method, `inputAllBaseTypes`, that inputs a different value of each base type from the standard 4 | input device and prints it back to the standard output device. 5 | **R-1.2** Suppose that we create an array `A` of `GameEntry` objects, which has an integer `scores` field, and we clone `A` and 6 | store the result in an array `B`. If we then immediately set `A[4].scores` equal to 550, what is the score value of the 7 | `GameEntry` object referenced by `B[4]`? 8 | **R-1.3** Write a short Java method, `isMultiple`, that takes two `long` values, *n* and *m*, and returns true if and only if *n* is a multiple of *m*, that is, $n = mi$ for some integer *i*. 9 | **R-1.4** Write a short Java method, `isEven`, that takes an int i and returns true if and only if i is even. Your method cannot use the multiplication, modulus, or division operators, however. 10 | **R-1.5** Write a short Java method that takes an integer n and returns the sum of all positive integers less than or equal to n. 11 | **R-1.6** Write a short Java method that takes an integer n and returns the sum of all the odd positive integers less than or equal to n. 12 | **R-1.7** Write a short Java method that takes an integer n and returns the sum of the squares of all positive integers less than or equal to n. 13 | **R-1.8** Write a short Java method that counts the number of vowel in a given character string. 14 | **R-1.9** Write a short Java method that uses a `StringBuilder` instance to remove all the punctuation from a string s storing a sentence, for example, transforming the string "Let's try, Mike!" to "Lets try Mike". 15 | **R-1.10** Write a Java class, Flower, that has three instance variables of type String, int, and float, which respectively represent the name of the flower, its number of petals, and price. Your class must include a constructor method that initializes each variable to an appropriate value, and your class should include methods for setting the value of each type, and getting the value of each type. 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06/src/main/java/MatchingTags.java: -------------------------------------------------------------------------------- 1 | public class MatchingTags { 2 | 3 | // Tests if delimiters in the given expression are properly matched. 4 | public static boolean isMatched(String expression) { 5 | final String opening = "({["; // opening delimiters 6 | final String closing = ")}]"; // respective closing delimiters 7 | 8 | Stack buffer = new LinkedStack<>(); 9 | for (char c : expression.toCharArray()) { 10 | if (opening.indexOf(c) != -1) // this is a left delimiter 11 | buffer.push(c); 12 | else if (closing.indexOf(c) != -1) // this is a right delimiter 13 | if (buffer.isEmpty()) // nothing to match with 14 | return false; 15 | if (closing.indexOf(c) != opening.indexOf(buffer.pop())) 16 | return false; // mismatched delimiter 17 | } 18 | return buffer.isEmpty(); // were all opening delimiters matched? 19 | } 20 | 21 | // Tests if every opening tag has a matching closing tag in HTML string. 22 | public static boolean isHTMLMatched(String html) { 23 | Stack buffer = new LinkedStack<>(); 24 | int j = html.indexOf('<'); // find first '<' character (if any) 25 | while (j != -1) { 26 | int k = html.indexOf('>', j + 1); // find next '>' character 27 | if (k == -1) 28 | return false; // invalid tag 29 | String tag = html.substring(j + 1, k); // strip away < > 30 | if (!tag.startsWith("/")) // this is an opening tag 31 | buffer.push(tag); 32 | else { 33 | if (buffer.isEmpty()) // this is a closing tag 34 | return false; // no tag to match 35 | if (!tag.substring(1).equals(buffer.pop())) 36 | return false; // mismatched tag 37 | } 38 | j = html.indexOf('<', k + 1); // find next '<' character (if any) 39 | } 40 | return buffer.isEmpty(); // were all opening tags matched? 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ch09/src/main/java/UnsortedPriorityQueue.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | /** 4 | * An implementation of a priority queue with an unsorted list. 5 | * @param 6 | * @param 7 | */ 8 | public class UnsortedPriorityQueue extends AbstractPriorityQueue { 9 | 10 | /** 11 | * primary collection of priority queue entries. 12 | */ 13 | private PositionalList> list = new LinkedPositionalList<>(); 14 | 15 | /** 16 | * Creates an empty priority queue based on the natual ordering of its keys. 17 | */ 18 | public UnsortedPriorityQueue() { 19 | super(); 20 | } 21 | 22 | public UnsortedPriorityQueue(Comparator comp) { 23 | super(comp); 24 | } 25 | 26 | private Position> findMin() { // only called when nonempty 27 | Position> small = list.first(); 28 | for (Position> walk: list.positions()) 29 | if (compare(walk.getElement(), small.getElement()) < 0) 30 | small = walk; // found an even smaller key 31 | return small; 32 | } 33 | 34 | 35 | 36 | @Override 37 | public int size() { 38 | return list.size(); 39 | } 40 | 41 | /** 42 | * Insets a key-value pair and returns the entry created. 43 | */ 44 | @Override 45 | public Entry insert(K key, V value) throws IllegalArgumentException { 46 | checkKey(key); // auxiliary key-checking method (cloud throw exception) 47 | Entry newest = new PQEntry<>(key, value); 48 | list.addLast(newest); 49 | return newest; 50 | } 51 | 52 | /** 53 | * Returns (but does not remove) an entry with minimal key. 54 | */ 55 | @Override 56 | public Entry min() { 57 | if (list.isEmpty()) return null; 58 | return findMin().getElement(); 59 | } 60 | 61 | /** 62 | * Removes and returns an entry with minimal key. 63 | */ 64 | @Override 65 | public Entry removeMin() { 66 | if (list.isEmpty()) return null; 67 | return list.remove(findMin()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ch13/src/main/java/LCS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | public class LCS { 25 | 26 | /** Returns table such that L[j][k] is length of LCS for X[0..j-1] and Y[0..k-1]. */ 27 | public static int[][] LCS(char[] X, char[] Y) { 28 | int n = X.length; 29 | int m = Y.length; 30 | int[][] L = new int[n+1][m+1]; 31 | for (int j=0; j < n; j++) 32 | for (int k=0; k < m; k++) 33 | if (X[j] == Y[k]) // align this match 34 | L[j+1][k+1] = L[j][k] + 1; 35 | else // choose to ignore one character 36 | L[j+1][k+1] = Math.max(L[j][k+1], L[j+1][k]); 37 | return L; 38 | } 39 | 40 | /** Returns the longest common substring of X and Y, given LCS table L. */ 41 | public static char[] reconstructLCS(char[] X, char[] Y, int[][] L) { 42 | StringBuilder solution = new StringBuilder(); 43 | int j = X.length; 44 | int k = Y.length; 45 | while (L[j][k] > 0) // common characters remain 46 | if (X[j-1] == Y[k-1]) { 47 | solution.append(X[j-1]); 48 | j--; 49 | k--; 50 | } else if (L[j-1][k] >= L[j][k-1]) 51 | j--; 52 | else 53 | k--; 54 | // return left-to-right version, as char array 55 | return solution.reverse().toString().toCharArray(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /ch10/src/main/java/AbstractHashMap.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Random; 3 | 4 | public abstract class AbstractHashMap extends AbstractMap { 5 | protected int n = 0; // number of entries in the dictionary 6 | protected int capacity; // length of the table 7 | private int prime; // prime factor 8 | private long scale, shift; // the shift and scaling factors 9 | 10 | public AbstractHashMap(int cap, int p) { 11 | prime = p; 12 | capacity = cap; 13 | Random rand = new Random(); 14 | scale = rand.nextInt(prime - 1) + 1; 15 | shift = rand.nextInt(prime); 16 | createTable(); 17 | } 18 | 19 | public AbstractHashMap(int cap) { 20 | this(cap, 109345121); // default prime 21 | } 22 | 23 | public AbstractHashMap() { 24 | this(17); // default capacity 25 | } 26 | 27 | // public methods 28 | public int size() { 29 | return n; 30 | } 31 | 32 | public V get(K key) { 33 | return bucketGet(hashValue(key), key); 34 | } 35 | 36 | public V remove(K key) { 37 | return bucketRemove(hashValue(key), key); 38 | } 39 | 40 | public V put(K key, V value) { 41 | V answer = bucketPut(hashValue(key), key, value); 42 | if (n > capacity / 2) 43 | resize(2 * capacity - 1); 44 | return answer; 45 | } 46 | 47 | // private utilities 48 | private int hashValue(K key) { 49 | return (int) ((Math.abs(key.hashCode() * scale + shift) % prime) % capacity); 50 | } 51 | 52 | private void resize(int newCap) { 53 | ArrayList> buffer = new ArrayList<>(n); 54 | for (Entry e : entrySet()) 55 | buffer.add(e); 56 | capacity = newCap; 57 | createTable(); // based on updated capacity 58 | n = 0; // will be recomputed while reinserting entries 59 | for (Entry e : buffer) 60 | put(e.getKey(), e.getValue()); 61 | } 62 | 63 | // protected abstract methods to be implemented by subclasses 64 | protected abstract void createTable(); 65 | 66 | protected abstract V bucketGet(int h, K k); 67 | 68 | protected abstract V bucketPut(int h, K k, V v); 69 | 70 | protected abstract V bucketRemove(int h, K k); 71 | } 72 | -------------------------------------------------------------------------------- /ch09/src/main/java/AbstractPriorityQueue.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | public abstract class AbstractPriorityQueue implements PriorityQueue { 4 | 5 | // ----------------- nested PQEntry class ------------------- 6 | protected static class PQEntry implements Entry { 7 | private K k; // key 8 | private V v; // value 9 | 10 | public PQEntry(K key, V value) { 11 | k = key; 12 | v = value; 13 | } 14 | 15 | // methods for the Entry interface 16 | @Override 17 | public K getKey() { 18 | return k; 19 | } 20 | 21 | @Override 22 | public V getValue() { 23 | return v; 24 | } 25 | 26 | protected void setKey(K key) { k = key; } 27 | protected void setValue(V value) { v = value; } 28 | } // --------------- end of nested PQEntry class ------------- 29 | 30 | // instance variable for an AbstractPriorityQueue 31 | /** 32 | * The Comparator defining the ordering of keys in the priority queue. 33 | */ 34 | private Comparator comp; // order by key 35 | /** 36 | * Creates an empty priority queue using the given comparator to order keys. 37 | */ 38 | protected AbstractPriorityQueue(Comparator c) { comp = c; } 39 | /** 40 | * Creates an empty priority queue based on the natural ordering of its keys. 41 | */ 42 | protected AbstractPriorityQueue() { 43 | this(new DefaultComparator()); 44 | } 45 | 46 | protected int compare(Entry a, Entry b) { 47 | return comp.compare(a.getKey(), b.getKey()); 48 | } 49 | 50 | /** Determines whether a key is valid. 51 | * 52 | * @param key key 53 | * @return true if valid false otherwise 54 | * @throws IllegalArgumentException if something goes wrong 55 | */ 56 | protected boolean checkKey(K key) throws IllegalArgumentException { 57 | try { 58 | return (comp.compare(key, key) == 0); // see if key can be compared to itself 59 | } catch (ClassCastException e) { 60 | throw new IllegalArgumentException("Incompatible key"); 61 | } 62 | } 63 | 64 | /** 65 | * Tests whether the priority queue is empty. 66 | */ 67 | public boolean isEmpty() { return size() == 0; } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /ch09/src/main/java/PriorityQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | /** 25 | * Interface for the priority queue ADT. 26 | * 27 | * @author Michael T. Goodrich 28 | * @author Roberto Tamassia 29 | * @author Michael H. Goldwasser 30 | */ 31 | public interface PriorityQueue { 32 | 33 | /** 34 | * Returns the number of items in the priority queue. 35 | * @return number of items 36 | */ 37 | int size(); 38 | 39 | /** 40 | * Tests whether the priority queue is empty. 41 | * @return true if the priority queue is empty, false otherwise 42 | */ 43 | boolean isEmpty(); 44 | 45 | /** 46 | * Inserts a key-value pair and returns the entry created. 47 | * @param key the key of the new entry 48 | * @param value the associated value of the new entry 49 | * @return the entry storing the new key-value pair 50 | * @throws IllegalArgumentException if the key is unacceptable for this queue 51 | */ 52 | Entry insert(K key, V value) throws IllegalArgumentException; 53 | 54 | /** 55 | * Returns (but does not remove) an entry with minimal key. 56 | * @return entry having a minimal key (or null if empty) 57 | */ 58 | Entry min(); 59 | 60 | /** 61 | * Removes and returns an entry with minimal key. 62 | * @return the removed entry (or null if empty) 63 | */ 64 | Entry removeMin(); 65 | } 66 | -------------------------------------------------------------------------------- /ch03/src/main/java/CaesarCipher.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Class for doing encryption and decryption using the Caesar Cipher. 3 | */ 4 | public class CaesarCipher { 5 | protected char[] encoder = new char[26]; 6 | protected char[] decoder = new char[26]; 7 | 8 | public CaesarCipher(int rotation) { 9 | for (int k = 0; k < 26; k++) { 10 | encoder[k] = (char) ('A' + (k + rotation) % 26); 11 | decoder[k] = (char) ('A' + (k - rotation + 26) % 26); 12 | } 13 | } 14 | 15 | public String encrypt(String message) { 16 | return transform(message, encoder); 17 | } 18 | 19 | public String decrypt(String secret) { 20 | return transform(secret, decoder); 21 | } 22 | 23 | private String transform(String original, char[] code) { 24 | char[] msg = original.toCharArray(); 25 | for (int k = 0; k < msg.length; k++) { 26 | if (Character.isUpperCase(msg[k])) { // we have a letter to change 27 | int j = msg[k] - 'A'; // will be value from 0 to 25 28 | msg[k] = code[j]; // replace the character 29 | } 30 | } 31 | return new String(msg); 32 | } 33 | 34 | public static void main(String[] args) { 35 | CaesarCipher cipher = new CaesarCipher(3); 36 | System.out.println("Encryption code = " + new String(cipher.encoder)); 37 | System.out.println("Decryption code = " + new String(cipher.decoder)); 38 | String message = "THE EAGLE IS IN PLAY; MEET AT JOE'S"; 39 | String coded = cipher.encrypt(message); 40 | System.out.println("Secret: " + coded); 41 | String answer = cipher.decrypt(coded); 42 | System.out.println("Message: " + answer); 43 | int x = 5 % (-3); 44 | int y = (-5) % (3); 45 | int z = (-5) % (-3); 46 | System.out.printf("%d, %d, %d", x, y, z); 47 | 48 | // 所以 % 是 remainder operator 49 | // modulo operator vs. remainder operator ? 50 | // As define in C, the % operation for a % b as: 51 | // a == (a / b * b) + a % b 52 | 53 | // Modulo and remainder operators differ with respect to negative values. 54 | // With a remainder operator, the sign of the result is the same as the sign 55 | // of the dividend while with a modulo operator the sign of the result is the 56 | // same as the divisor. 57 | 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ch09/src/main/java/AdaptablePriorityQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | 25 | /** 26 | * Interface for the adaptable priority queue ADT. The Entry instance 27 | * returned by the insert method can later be used to remove the 28 | * entry, or to modify that entry's key or value. 29 | * 30 | * @author Michael T. Goodrich 31 | * @author Roberto Tamassia 32 | * @author Michael H. Goldwasser 33 | */ 34 | public interface AdaptablePriorityQueue extends PriorityQueue { 35 | 36 | /** 37 | * Removes the given entry from the priority queue. 38 | * 39 | * @param entry an entry of this priority queue 40 | * @throws IllegalArgumentException if e is not a valid entry for the priority queue. 41 | */ 42 | void remove(Entry entry) throws IllegalArgumentException; 43 | 44 | /** 45 | * Replaces the key of an entry. 46 | * 47 | * @param entry an entry of this priority queue 48 | * @param key the new key 49 | * @throws IllegalArgumentException if e is not a valid entry for the priority queue. 50 | */ 51 | void replaceKey(Entry entry, K key) throws IllegalArgumentException; 52 | 53 | /** 54 | * Replaces the value of an entry. 55 | * 56 | * @param entry an entry of this priority queue 57 | * @param value the new value 58 | * @throws IllegalArgumentException if e is not a valid entry for the priority queue. 59 | */ 60 | void replaceValue(Entry entry, V value) throws IllegalArgumentException; 61 | } 62 | -------------------------------------------------------------------------------- /ch08/src/main/java/AbstractBinaryTree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * An abstract base class providing some functionality of the BinaryTree interface. 3 | * 4 | * @param 5 | */ 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public abstract class AbstractBinaryTree extends AbstractTree implements BinaryTree { 11 | 12 | /** 13 | * @param p position in question 14 | * @return the Position of p's sibling (or null if no sibling exists). 15 | */ 16 | public Position sibling(Position p) { 17 | Position parent = parent(p); 18 | if (parent == null) return null; // p must be the root 19 | if (p == left(parent)) // p is a left child 20 | return right(parent); // right child might be null 21 | else // p is a right child 22 | return left(parent); // (left child might be null) 23 | } 24 | 25 | /** 26 | * @param p the position which the subtree rooted. 27 | * @return the number of children of Position p. 28 | */ 29 | public int numChildren(Position p) { 30 | int count = 0; 31 | if (left(p) != null) 32 | count++; 33 | if (right(p) != null) 34 | count++; 35 | return count; 36 | } 37 | 38 | public Iterable> children(Position p) { 39 | // 这里用的是 java.util.List 和 java.util.ArrayList 而不是 ch07 自定义的 List 和 ArrayList 40 | List> snapshot = new ArrayList<>(2); // max capacity of 2 41 | if (left(p) != null) 42 | snapshot.add(left(p)); 43 | if (right(p) != null) 44 | snapshot.add(right(p)); 45 | return snapshot; 46 | } 47 | 48 | /** 49 | * Adds positions of the subtree rooted at Position p to the given snapshot. 50 | */ 51 | private void inorderSubtree(Position p, List> snapshot) { 52 | if (left(p) != null) 53 | inorderSubtree(left(p), snapshot); 54 | snapshot.add(p); 55 | if (right(p) != null) 56 | inorderSubtree(right(p), snapshot); 57 | } 58 | 59 | /** 60 | * Returns an iterable collection of positions of the tree, reported in inorder. 61 | */ 62 | public Iterable> inorder() { 63 | List> snapshot = new ArrayList<>(); 64 | if (!isEmpty()) 65 | inorderSubtree(root(), snapshot); // fill the snapshot recursively 66 | return snapshot; 67 | } 68 | 69 | /** 70 | * Overrides positions to make inorder the default order for binary trees. 71 | */ 72 | @Override 73 | public Iterable> positions() { 74 | return inorder(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /ch10/src/main/java/HashMultimap.java: -------------------------------------------------------------------------------- 1 | import java.util.AbstractMap; 2 | import java.util.ArrayList; 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | public class HashMultimap { 8 | Map> map = new HashMap<>(); // the primary map 9 | int total = 0; // total number of entries in the multimap 10 | 11 | /** 12 | * Constructs an empty multimap. 13 | */ 14 | public HashMultimap() { 15 | } 16 | 17 | /** 18 | * Returns the total number of entries in the multimap 19 | */ 20 | public int size() { 21 | return total; 22 | } 23 | 24 | /** 25 | * Returns whether the multimap is empty. 26 | */ 27 | public boolean isEmpty() { 28 | return (total == 0); 29 | } 30 | 31 | /** 32 | * Returns a (possibly empty) iteration of all values associated with the key. 33 | */ 34 | Iterable get(K key) { 35 | List secondary = map.get(key); 36 | if (secondary != null) 37 | return secondary; 38 | return new ArrayList<>(); // return an empty list of values 39 | } 40 | 41 | void put(K key, V value) { 42 | List secondary = map.get(key); 43 | if (secondary == null) { 44 | secondary = new ArrayList<>(); 45 | map.put(key, secondary); // begin using new list as secondary structure 46 | } 47 | secondary.add(value); 48 | total++; 49 | } 50 | 51 | boolean remove(K key, V value) { 52 | boolean wasRemoved = false; 53 | List secondary = map.get(key); 54 | if (secondary != null) { 55 | wasRemoved = secondary.remove(value); 56 | if (wasRemoved) { 57 | total--; 58 | if (secondary.isEmpty()) 59 | map.remove(key); // remove secondary structure from primary map 60 | } 61 | } 62 | return wasRemoved; 63 | } 64 | 65 | Iterable removeAll(K key) { 66 | List secondary = map.get(key); 67 | if (secondary != null) { 68 | total -= secondary.size(); 69 | map.remove(key); 70 | } else 71 | secondary = new ArrayList<>(); // return empty list of removed values 72 | return secondary; 73 | } 74 | 75 | Iterable> entries() { 76 | List> result = new ArrayList<>(); 77 | for (Map.Entry> secondary : map.entrySet()) { 78 | K key = secondary.getKey(); 79 | for (V value : secondary.getValue()) 80 | result.add(new AbstractMap.SimpleEntry(key, value)); // 这行有点意思, AbstractMap.SimpleEntry 81 | } 82 | return result; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /ch03/src/main/java/CircularlyLinkedList.java: -------------------------------------------------------------------------------- 1 | public class CircularlyLinkedList { 2 | private static class Node { 3 | private E element; 4 | private Node next; 5 | 6 | public Node(E e, Node n) { 7 | element = e; 8 | next = n; 9 | } 10 | 11 | public E getElement() { 12 | return element; 13 | } 14 | 15 | public Node getNext() { 16 | return next; 17 | } 18 | 19 | public void setNext(Node n) { 20 | next = n; 21 | } 22 | } 23 | 24 | // instance variables of the CircularlyLinkedList 25 | private Node tail = null; // we store tail (but not head) 26 | private int size = 0; // number of nodes in the list 27 | 28 | public CircularlyLinkedList() { } // constructors an initially empty list 29 | 30 | // access methods 31 | public int size() { 32 | return size; 33 | } 34 | 35 | public boolean isEmpty() { 36 | return size == 0; 37 | } 38 | 39 | public E first() { 40 | if (isEmpty()) { 41 | return null; 42 | } 43 | return tail.getNext().getElement(); // the head is *after* the tail 44 | } 45 | 46 | public E last() { // returns (but does not remove) the last element 47 | if (isEmpty()) { 48 | return null; 49 | } 50 | return tail.getElement(); 51 | } 52 | 53 | // update methods 54 | public void rotate() { // rotate the first element to the back of the list 55 | if (tail != null) { // if empty, do nothing 56 | tail = tail.getNext(); // the old head becomes the new tail 57 | } 58 | } 59 | 60 | public void addFirst(E e) { // adds element e to the front of the list 61 | if (size == 0) { 62 | tail = new Node<>(e, null); 63 | tail.setNext(tail); // link to itself circularly 64 | } else { 65 | Node newest = new Node<>(e, tail.getNext()); 66 | tail.setNext(newest); 67 | } 68 | size++; 69 | } 70 | 71 | public void addLast(E e) { // adds element e to the end of the list 72 | addFirst(e); // insert new element at front of list 73 | tail = tail.getNext(); // now new element becomes the tail 74 | } 75 | 76 | public E removeFirst() { // removes and returns the first element 77 | if (isEmpty()) { 78 | return null; // nothing to remove 79 | } 80 | Node head = tail.getNext(); 81 | if (head == tail) { 82 | tail = null; // must be the only node left 83 | } else { 84 | tail.setNext(head.getNext()); // removes "head" from the list 85 | } 86 | size--; 87 | return head.getElement(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ch06/src/main/java/CircularlyLinkedList.java: -------------------------------------------------------------------------------- 1 | public class CircularlyLinkedList { 2 | private static class Node { 3 | private E element; 4 | private Node next; 5 | 6 | public Node(E e, Node n) { 7 | element = e; 8 | next = n; 9 | } 10 | 11 | public E getElement() { 12 | return element; 13 | } 14 | 15 | public Node getNext() { 16 | return next; 17 | } 18 | 19 | public void setNext(Node n) { 20 | next = n; 21 | } 22 | } 23 | 24 | // instance variables of the CircularlyLinkedList 25 | private Node tail = null; // we store tail (but not head) 26 | private int size = 0; // number of nodes in the list 27 | 28 | public CircularlyLinkedList() { } // constructors an initially empty list 29 | 30 | // access methods 31 | public int size() { 32 | return size; 33 | } 34 | 35 | public boolean isEmpty() { 36 | return size == 0; 37 | } 38 | 39 | public E first() { 40 | if (isEmpty()) { 41 | return null; 42 | } 43 | return tail.getNext().getElement(); // the head is *after* the tail 44 | } 45 | 46 | public E last() { // returns (but does not remove) the last element 47 | if (isEmpty()) { 48 | return null; 49 | } 50 | return tail.getElement(); 51 | } 52 | 53 | // update methods 54 | public void rotate() { // rotate the first element to the back of the list 55 | if (tail != null) { // if empty, do nothing 56 | tail = tail.getNext(); // the old head becomes the new tail 57 | } 58 | } 59 | 60 | public void addFirst(E e) { // adds element e to the front of the list 61 | if (size == 0) { 62 | tail = new Node<>(e, null); 63 | tail.setNext(tail); // link to itself circularly 64 | } else { 65 | Node newest = new Node<>(e, tail.getNext()); 66 | tail.setNext(newest); 67 | } 68 | size++; 69 | } 70 | 71 | public void addLast(E e) { // adds element e to the end of the list 72 | addFirst(e); // insert new element at front of list 73 | tail = tail.getNext(); // now new element becomes the tail 74 | } 75 | 76 | public E removeFirst() { // removes and returns the first element 77 | if (isEmpty()) { 78 | return null; // nothing to remove 79 | } 80 | Node head = tail.getNext(); 81 | if (head == tail) { 82 | tail = null; // must be the only node left 83 | } else { 84 | tail.setNext(head.getNext()); // removes "head" from the list 85 | } 86 | size--; 87 | return head.getElement(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ch07/src/main/java/PositionalList.java: -------------------------------------------------------------------------------- 1 | /** 2 | * An interface for positional lists. 3 | * 4 | * @param element 5 | */ 6 | public interface PositionalList extends Iterable { 7 | 8 | Iterable> positions(); 9 | 10 | /** 11 | * Returns the number of elements in the list. 12 | */ 13 | int size(); 14 | 15 | /** 16 | * Tests whether the list is empty. 17 | */ 18 | boolean isEmpty(); 19 | 20 | /** 21 | * Returns the first Position in the list (or null, if empty). 22 | */ 23 | Position first(); 24 | 25 | /** 26 | * Returns the last Position in the list (or null, if empty). 27 | */ 28 | Position last(); 29 | 30 | /** 31 | * @param p position 32 | * @return the Position immediately before Position p (or null, if p is first). 33 | * @throws IllegalArgumentException if Position is not valid. 34 | */ 35 | Position before(Position p) throws IllegalArgumentException; 36 | 37 | /** 38 | * @param p position 39 | * @return the Position immediately after Position p (or null, if p is last). 40 | * @throws IllegalArgumentException if Position is not valid. 41 | */ 42 | Position after(Position p) throws IllegalArgumentException; 43 | 44 | /** 45 | * Inserts element e at the front of the list and returns its new Position. 46 | * 47 | * @param e the element to be added. 48 | * @return its new Position 49 | */ 50 | Position addFirst(E e); 51 | 52 | /** 53 | * Inserts element e at the back of the list and returns its new Position. 54 | * 55 | * @param e the element to be added. 56 | * @return its new Position 57 | */ 58 | Position addLast(E e); 59 | 60 | /** 61 | * @param p the Position 62 | * @param e the element to be added 63 | * @return its new Position 64 | * @throws IllegalArgumentException if the Position invalid. 65 | */ 66 | Position addBefore(Position p, E e) throws IllegalArgumentException; 67 | 68 | /** 69 | * @param p the Position 70 | * @param e the element to be added 71 | * @return its new Position 72 | * @throws IllegalArgumentException if the Position invalid. 73 | */ 74 | Position addAfter(Position p, E e) throws IllegalArgumentException; 75 | 76 | /** 77 | * Replaces the element stored at Position p and returns the replaced element. 78 | * 79 | * @param p the position 80 | * @param e the new element at Position p 81 | * @return the replaced element 82 | * @throws IllegalArgumentException if the position invalid 83 | */ 84 | E set(Position p, E e) throws IllegalArgumentException; 85 | 86 | /** 87 | * Removes the element stored at Position p and returns it (invalidating p). 88 | * 89 | * @param p the position in which the element to be removed 90 | * @return the removed element 91 | * @throws IllegalArgumentException 92 | */ 93 | E remove(Position p) throws IllegalArgumentException; 94 | 95 | } 96 | -------------------------------------------------------------------------------- /ch11/src/main/java/SplayTreeMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | import java.util.Comparator; 25 | 26 | /** 27 | * An implementation of a sorted map using a splay tree. 28 | * 29 | * @author Michael T. Goodrich 30 | * @author Roberto Tamassia 31 | * @author Michael H. Goldwasser 32 | */ 33 | public class SplayTreeMap extends TreeMap { 34 | 35 | /** Constructs an empty map using the natural ordering of keys. */ 36 | public SplayTreeMap() { super(); } 37 | 38 | /** 39 | * Constructs an empty map using the given comparator to order keys. 40 | * @param comp comparator defining the order of keys in the map 41 | */ 42 | public SplayTreeMap(Comparator comp) { super(comp); } 43 | 44 | /** Utility used to rebalance after a map operation. */ 45 | private void splay(Position> p) { 46 | while (!isRoot(p)) { 47 | Position> parent = parent(p); 48 | Position> grand = parent(parent); 49 | if (grand == null) // zig case 50 | rotate(p); 51 | else if ((parent == left(grand)) == (p == left(parent))) { // zig-zig case 52 | rotate(parent); // move PARENT upward 53 | rotate(p); // then move p upward 54 | } else { // zig-zag case 55 | rotate(p); // move p upward 56 | rotate(p); // move p upward again 57 | } 58 | } 59 | } 60 | 61 | /** Overrides the TreeMap rebalancing hook that is called after a node access. */ 62 | @Override 63 | protected void rebalanceAccess(Position> p) { 64 | if (isExternal(p)) p = parent(p); 65 | if (p != null) splay(p); 66 | } 67 | 68 | /** Overrides the TreeMap rebalancing hook that is called after an insertion. */ 69 | @Override 70 | protected void rebalanceInsert(Position> p) { 71 | splay(p); 72 | } 73 | 74 | /** Overrides the TreeMap rebalancing hook that is called after a deletion. */ 75 | @Override 76 | protected void rebalanceDelete(Position> p) { 77 | if (!isRoot(p)) splay(parent(p)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /ch14/src/main/java/Partition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | /** A Union-Find structure for maintaining disjoint sets. */ 25 | public class Partition { 26 | 27 | //--------------- nested Locator class ------------- 28 | private class Locator implements Position { 29 | public E element; 30 | public int size; 31 | public Locator parent; 32 | public Locator(E elem) { 33 | element = elem; 34 | size = 1; 35 | parent = this; // convention for a cluster leader 36 | } 37 | 38 | public E getElement() { return element; } 39 | 40 | private boolean validate(Partition universe) { 41 | return Partition.this == universe; 42 | } 43 | } //--------- end of nested Locator class --------- 44 | 45 | /** Validates a Position and returns it cast as a Locator. */ 46 | private Locator validate(Position pos) { 47 | if (!(pos instanceof Locator)) throw new IllegalArgumentException("Invalid position"); 48 | Locator loc = (Locator) pos; 49 | if (!loc.validate(this)) 50 | throw new IllegalArgumentException("Position does not belong to this structure"); 51 | return loc; 52 | } 53 | 54 | /** Makes a new cluster containing element e and returns its position. */ 55 | public Position makeCluster(E e) { 56 | return new Locator(e); 57 | } 58 | 59 | /** 60 | * Finds the cluster containing the element identified by Position p 61 | * and returns the Position of the cluster's leader. 62 | */ 63 | public Position find(Position p) { 64 | Locator loc = validate(p); 65 | if (loc.parent != loc) 66 | loc.parent = (Locator) find(loc.parent); // overwrite parent after recursion 67 | return loc.parent; 68 | } 69 | 70 | /** Merges the clusters containing elements with positions p and q (if distinct). */ 71 | public void union(Position p, Position q) { 72 | Locator a = (Locator) find(p); 73 | Locator b = (Locator) find(q); 74 | if (a != b) 75 | if (a.size > b.size) { 76 | b.parent = a; 77 | a.size += b.size; 78 | } else { 79 | a.parent = b; 80 | b.size += a.size; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /ch10/src/main/java/AbstractMap.java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | 3 | public abstract class AbstractMap implements Map { 4 | 5 | @Override 6 | public boolean isEmpty() { 7 | return size() == 0; 8 | } 9 | 10 | // --------------- nested MapEntry class ------------------ 11 | protected static class MapEntry implements Entry { 12 | private K k; // key 13 | private V v; // value 14 | 15 | public MapEntry(K key, V value) { 16 | k = key; 17 | v = value; 18 | } 19 | 20 | // public methods of the Entry interface 21 | @Override 22 | public K getKey() { 23 | return k; 24 | } 25 | 26 | @Override 27 | public V getValue() { 28 | return v; 29 | } 30 | 31 | // utilities not exposed as part of the Entry interface 32 | protected void setKey(K key) { 33 | k = key; 34 | } 35 | 36 | protected V setValue(V value) { 37 | V old = v; 38 | v = value; 39 | return old; 40 | } 41 | 42 | /** 43 | * Returns string representation (for debugging only) 44 | */ 45 | public String toString() { 46 | return "<" + k + ", " + v + ">"; 47 | } 48 | } // ----------- end of nested MapEntry class -------------- 49 | 50 | // Support for public keySet method... 51 | private class KeyIterator implements Iterator { 52 | private Iterator> entries = entrySet().iterator(); // reuse entrySet 53 | 54 | @Override 55 | public boolean hasNext() { 56 | return entries.hasNext(); 57 | } 58 | 59 | @Override 60 | public K next() { 61 | return entries.next().getKey(); // return key! 62 | } 63 | 64 | @Override 65 | public void remove() { 66 | throw new UnsupportedOperationException(); 67 | } 68 | } 69 | 70 | private class KeyIterable implements Iterable { 71 | @Override 72 | public Iterator iterator() { 73 | return new KeyIterator(); 74 | } 75 | } 76 | 77 | @Override 78 | public Iterable keySet() { 79 | return new KeyIterable(); 80 | } 81 | 82 | // Support for public values method... 83 | private class ValueIterator implements Iterator { 84 | private Iterator> entries = entrySet().iterator(); // reuse entrySet 85 | 86 | @Override 87 | public boolean hasNext() { 88 | return entries.hasNext(); 89 | } 90 | 91 | @Override 92 | public V next() { 93 | return entries.next().getValue(); // return value! 94 | } 95 | 96 | @Override 97 | public void remove() { 98 | throw new UnsupportedOperationException(); 99 | } 100 | } 101 | 102 | private class ValueIterable implements Iterable { 103 | @Override 104 | public Iterator iterator() { 105 | return new ValueIterator(); 106 | } 107 | } 108 | 109 | @Override 110 | public Iterable values() { 111 | return new ValueIterable(); 112 | } 113 | 114 | 115 | } 116 | -------------------------------------------------------------------------------- /ch03/src/main/java/TicTacToe.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Simulation of a Tic-Tac-Toe game (does not do strategy). 3 | */ 4 | public class TicTacToe { 5 | public static final int X = 1, O = -1; // players 6 | public static final int EMPTY = 0; 7 | private int board[][] = new int[3][3]; 8 | private int player; 9 | 10 | public TicTacToe() { 11 | clearBoard(); 12 | } 13 | 14 | public void clearBoard() { 15 | for (int i = 0; i < 3; i++) { 16 | for (int j = 0; j < 3; j++) { 17 | board[i][j] = EMPTY; 18 | } 19 | } 20 | player = X; 21 | } 22 | 23 | public void putMark(int i, int j) throws IllegalArgumentException { 24 | if ((i < 0) || (i > 2) || (j < 0) || (j > 2)) { 25 | throw new IllegalArgumentException("Invalid board position"); 26 | } 27 | if (board[i][j] != EMPTY) { 28 | throw new IllegalArgumentException("Board position occupied!"); 29 | } 30 | board[i][j] = player; 31 | player = -player; 32 | } 33 | 34 | public boolean isWin(int mark) { 35 | return ((board[0][0] + board[0][1] + board[0][2] == mark * 3) // row 0 36 | || (board[1][0] + board[1][1] + board[1][2] == mark * 3) // row 1 37 | || (board[2][0] + board[2][1] + board[2][2] == mark * 3) // row 2 38 | || (board[0][0] + board[1][0] + board[2][0] == mark * 3) // column 0 39 | || (board[0][1] + board[1][1] + board[2][1] == mark * 3) // column 1 40 | || (board[0][2] + board[1][2] + board[2][2] == mark * 3) // column 2 41 | || (board[0][0] + board[1][1] + board[2][2] == mark * 3) // diagonal 42 | || (board[2][0] + board[1][1] + board[0][2] == mark * 3) // rev diag 43 | ); 44 | } 45 | 46 | public int winner() { 47 | if (isWin(X)) { 48 | return (X); 49 | } else if (isWin(O)) { 50 | return (O); 51 | } else return (0); 52 | } 53 | 54 | /** 55 | * Returns a simple character string showing the current board. 56 | */ 57 | public String toString() { 58 | StringBuilder sb = new StringBuilder(); 59 | for (int i = 0; i < 3; i++) { 60 | for (int j = 0; j < 3; j++) { 61 | switch (board[i][j]) { 62 | case X: 63 | sb.append("X"); break; 64 | case O: 65 | sb.append("O"); break; 66 | case EMPTY: 67 | sb.append(" "); break; 68 | } 69 | if (j < 2) { 70 | sb.append("|"); 71 | } 72 | } 73 | if (i < 2) { 74 | sb.append("\n-----\n"); 75 | } 76 | } 77 | return sb.toString(); 78 | } 79 | 80 | public static void main(String[] args) { 81 | TicTacToe game = new TicTacToe(); 82 | 83 | game.putMark(1, 1); game.putMark(0,2); 84 | game.putMark(2,2); game.putMark(0,0); 85 | game.putMark(0,1); game.putMark(2,1); 86 | game.putMark(1,2); game.putMark(1,0); 87 | game.putMark(2,0); 88 | System.out.println(game); 89 | int winningPlayer = game.winner(); 90 | String[] outcome = {" O wins", "Tie", "X wins"}; 91 | System.out.println(outcome[1 + winningPlayer]); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /ch10/src/main/java/UnsortedTableMap.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Iterator; 3 | import java.util.NoSuchElementException; 4 | 5 | public class UnsortedTableMap extends AbstractMap { 6 | /** 7 | * Underlying storage for the map of entries. 8 | */ 9 | private ArrayList> table = new ArrayList<>(); 10 | 11 | /** 12 | * Constructs an initially empty map. 13 | */ 14 | public UnsortedTableMap() { 15 | 16 | } 17 | 18 | // private utility 19 | 20 | /** 21 | * Returns the index of an entry with equal key, or -1 if none found. 22 | */ 23 | 24 | private int findIndex(K key) { 25 | int n = table.size(); 26 | for (int j = 0; j < n; j++) 27 | if (table.get(j).getKey().equals(key)) 28 | return j; 29 | return -1; // special value denotes that key was not found 30 | } 31 | 32 | /** 33 | * Returns the number of entries in the map. 34 | */ 35 | @Override 36 | public int size() { 37 | return table.size(); 38 | } 39 | 40 | /** 41 | * Returns the value associated with the specified key (or else null). 42 | */ 43 | @Override 44 | public V get(K key) { 45 | int j = findIndex(key); 46 | if (j == -1) return null; 47 | return table.get(j).getValue(); // not found 48 | } 49 | 50 | /** 51 | * Associates given value with given key, replacing a previous value (if any). 52 | */ 53 | @Override 54 | public V put(K key, V value) { 55 | int j = findIndex(key); 56 | if (j == -1) { 57 | table.add(new MapEntry<>(key, value)); // add new entry 58 | return null; 59 | } else 60 | return table.get(j).setValue(value); // replaced value is returned 61 | } 62 | 63 | 64 | /** 65 | * Removes the entry with the specified key (if any) and returns its value. 66 | */ 67 | @Override 68 | public V remove(K key) { 69 | int j = findIndex(key); 70 | int n = size(); 71 | if (j == -1) return null; 72 | V answer = table.get(j).getValue(); // relocate last entry to 'hole' created by removal 73 | table.remove(n - 1); 74 | return answer; 75 | } 76 | 77 | // Support for public entrySet method... 78 | private class EntryIterator implements Iterator> { 79 | private int j = 0; 80 | 81 | @Override 82 | public boolean hasNext() { 83 | return j < table.size(); 84 | } 85 | 86 | @Override 87 | public Entry next() { 88 | if (j == table.size()) throw new NoSuchElementException(); 89 | return table.get(j++); 90 | } 91 | 92 | @Override 93 | public void remove() { 94 | throw new UnsupportedOperationException(); 95 | } 96 | } 97 | 98 | private class EntryIterable implements Iterable> { 99 | @Override 100 | public Iterator> iterator() { 101 | return new EntryIterator(); 102 | } 103 | } 104 | 105 | /** 106 | * Returns an iterable collection of all key-value entries of the map. 107 | */ 108 | @Override 109 | public Iterable> entrySet() { 110 | return new EntryIterable(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /ch06/src/main/java/LinkedStack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | 25 | /** 26 | * Realization of a stack as an adaptation of a SinglyLinkedList. 27 | * All operations are performed in constant time. 28 | * 29 | * @author Michael T. Goodrich 30 | * @author Roberto Tamassia 31 | * @author Michael H. Goldwasser 32 | * @see SinglyLinkedList 33 | */ 34 | public class LinkedStack implements Stack { 35 | 36 | /** 37 | * The primary storage for elements of the stack 38 | */ 39 | private SinglyLinkedList list = new SinglyLinkedList<>(); // an empty list 40 | 41 | /** 42 | * Constructs an initially empty stack. 43 | */ 44 | public LinkedStack() { 45 | } // new stack relies on the initially empty list 46 | 47 | /** 48 | * Returns the number of elements in the stack. 49 | * 50 | * @return number of elements in the stack 51 | */ 52 | @Override 53 | public int size() { 54 | return list.size(); 55 | } 56 | 57 | /** 58 | * Tests whether the stack is empty. 59 | * 60 | * @return true if the stack is empty, false otherwise 61 | */ 62 | @Override 63 | public boolean isEmpty() { 64 | return list.isEmpty(); 65 | } 66 | 67 | /** 68 | * Inserts an element at the top of the stack. 69 | * 70 | * @param element the element to be inserted 71 | */ 72 | @Override 73 | public void push(E element) { 74 | list.addFirst(element); 75 | } 76 | 77 | /** 78 | * Returns, but does not remove, the element at the top of the stack. 79 | * 80 | * @return top element in the stack (or null if empty) 81 | */ 82 | @Override 83 | public E top() { 84 | return list.first(); 85 | } 86 | 87 | /** 88 | * Removes and returns the top element from the stack. 89 | * 90 | * @return element removed (or null if empty) 91 | */ 92 | @Override 93 | public E pop() { 94 | return list.removeFirst(); 95 | } 96 | 97 | /** 98 | * Produces a string representation of the contents of the stack. 99 | * (ordered from top to bottom) 100 | *

101 | * This exists for debugging purposes only. 102 | * 103 | * @return textual representation of the stack 104 | */ 105 | public String toString() { 106 | return list.toString(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /ch10/src/main/java/ChainHashMap.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | public class ChainHashMap extends AbstractHashMap { 4 | 5 | // a fixed capacity array of UnsortedTableMap that serve as buckets 6 | 7 | private UnsortedTableMap[] table; // initialized within createTable 8 | 9 | public ChainHashMap() { 10 | super(); 11 | } 12 | 13 | public ChainHashMap(int cap) { 14 | super(cap); 15 | } 16 | 17 | public ChainHashMap(int cap, int p) { 18 | super(cap, p); 19 | } 20 | 21 | @Override 22 | public int size() { 23 | return 0; 24 | } 25 | 26 | @Override 27 | public boolean isEmpty() { 28 | return false; 29 | } 30 | 31 | @Override 32 | public V get(K key) { 33 | return null; 34 | } 35 | 36 | @Override 37 | public V put(K key, V value) { 38 | return null; 39 | } 40 | 41 | /** 42 | * Creates an empty table having length equal to current capacity. 43 | */ 44 | @Override 45 | protected void createTable() { 46 | table = (UnsortedTableMap[]) new UnsortedTableMap[capacity]; 47 | } 48 | 49 | 50 | /** 51 | * Returns value associated with key k in bucket with has value h, or else null. 52 | * 53 | * @param h hash value 54 | * @param k key 55 | * @return value associated with key k 56 | */ 57 | @Override 58 | protected V bucketGet(int h, K k) { 59 | UnsortedTableMap bucket = table[h]; 60 | if (bucket == null) return null; 61 | return bucket.get(k); 62 | } 63 | 64 | /** 65 | * Associates key k with value v in bucket with hash value h; returns old value. 66 | */ 67 | @Override 68 | protected V bucketPut(int h, K k, V v) { 69 | UnsortedTableMap bucket = table[h]; 70 | if (bucket == null) 71 | bucket = table[h] = new UnsortedTableMap<>(); 72 | int oldSize = bucket.size(); 73 | V answer = bucket.put(k, v); 74 | n += (bucket.size() - oldSize); // size may have increased 75 | return answer; 76 | } 77 | 78 | /** 79 | * Removes entry having key k from bucket with hash value h (if any). 80 | */ 81 | @Override 82 | protected V bucketRemove(int h, K k) { 83 | UnsortedTableMap bucket = table[h]; 84 | if (bucket == null) return null; 85 | int oldSize = bucket.size(); 86 | V answer = bucket.remove(k); 87 | n -= (oldSize - bucket.size()); // size may have decreased 88 | return answer; 89 | } 90 | 91 | @Override 92 | public V remove(K key) { 93 | return null; 94 | } 95 | 96 | @Override 97 | public Iterable keySet() { 98 | return null; 99 | } 100 | 101 | @Override 102 | public Iterable values() { 103 | return null; 104 | } 105 | 106 | /** 107 | * 108 | * @return an iterable collection of all key-value entries of the map. 109 | */ 110 | @Override 111 | public Iterable> entrySet() { 112 | ArrayList> buffer = new ArrayList<>(); 113 | for (int h = 0; h < capacity; h++) 114 | if (table[h] != null) 115 | for (Entry entry : table[h].entrySet()) 116 | buffer.add(entry); 117 | return buffer; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /ch10/src/main/java/AbstractSortedMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | import java.util.Comparator; 25 | 26 | /** 27 | * An abstract base class to ease the implementation of the SortedMap interface. 28 | * 29 | * The base class provides four means of support: 30 | * 1) It defines a PQEntry class as a concrete implementation of the 31 | * entry interface 32 | * 2) It provides an instance variable for a general Comparator and 33 | * protected methods, compare(a, b), that can compare either two 34 | * entries or two keys using the comparator. 35 | * 3) It provides a boolean checkKey method that verifies that a given key 36 | * is appropriate for use with the comparator 37 | * 38 | * @author Michael T. Goodrich 39 | * @author Roberto Tamassia 40 | * @author Michael H. Goldwasser 41 | */ 42 | public abstract class AbstractSortedMap 43 | extends AbstractMap implements SortedMap { 44 | 45 | // instance variable for an AbstractSortedMap 46 | /** The comparator defining the ordering of keys in the map. */ 47 | private Comparator comp; 48 | 49 | /** 50 | * Initializes the comparator for the map. 51 | * @param c comparator defining the order of keys in the map 52 | */ 53 | protected AbstractSortedMap(Comparator c) { 54 | comp = c; 55 | } 56 | 57 | /** Initializes the map with a default comparator. */ 58 | protected AbstractSortedMap() { 59 | this(new DefaultComparator()); // default comparator uses natural ordering 60 | } 61 | 62 | /** Method for comparing two entries according to key */ 63 | protected int compare(Entry a, Entry b) { 64 | return comp.compare(a.getKey(), b.getKey()); 65 | } 66 | 67 | /** Method for comparing a key and an entry's key */ 68 | protected int compare(K a, Entry b) { 69 | return comp.compare(a, b.getKey()); 70 | } 71 | 72 | /** Method for comparing a key and an entry's key */ 73 | protected int compare(Entry a, K b) { 74 | return comp.compare(a.getKey(), b); 75 | } 76 | 77 | /** Method for comparing two keys */ 78 | protected int compare(K a, K b) { 79 | return comp.compare(a, b); 80 | } 81 | 82 | /** Determines whether a key is valid. */ 83 | protected boolean checkKey(K key) throws IllegalArgumentException { 84 | try { 85 | return (comp.compare(key,key)==0); // see if key can be compared to itself 86 | } catch (ClassCastException e) { 87 | throw new IllegalArgumentException("Incompatible key"); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ch01/src/main/java/CreditCard.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This {@code CreditCard} class defines credit card objects that model a simplified version of traditional credit cards. 3 | * They store information about the customer, issuing bank, account identifier, credit limit, and current balance. They 4 | * do not charge interest or late payments, but they do restrict charges that would cause a card's balance to go over its 5 | * credit limit. 6 | */ 7 | public class CreditCard { 8 | 9 | // Instance variables: 10 | private String customer; // name of the customer (e.g., "John Bowman") 11 | private String bank; // name of the bank (e.g., "California Savings") 12 | private String account; // account identifier (e.g., "5391 0375 9387 5309") 13 | private int limit; // credit limit (measure in dollars) 14 | protected double balance; // current balance (measure in dollars) 15 | 16 | // Constructors: 17 | public CreditCard(String customer, String bank, String account, int limit, double balance) { 18 | this.customer = customer; 19 | this.bank = bank; 20 | this.account = account; 21 | this.limit = limit; 22 | this.balance = balance; 23 | } 24 | 25 | public CreditCard(String customer, String bank, String account, int limit) { 26 | this(customer, bank, account, limit, 0.0); 27 | } 28 | 29 | public CreditCard() { 30 | 31 | } 32 | 33 | // Accessor methods: 34 | public String getCustomer() { 35 | return customer; 36 | } 37 | 38 | public String getBank() { 39 | return bank; 40 | } 41 | 42 | public String getAccount() { 43 | return account; 44 | } 45 | 46 | public int getLimit() { 47 | return limit; 48 | } 49 | 50 | public double getBalance() { 51 | return balance; 52 | } 53 | 54 | // Update methods: 55 | public boolean charge(double price) { 56 | if (price + balance > limit) { 57 | return false; 58 | } 59 | balance += price; 60 | return true; 61 | } 62 | 63 | public void makePayment(double amount) { 64 | balance -= amount; 65 | } 66 | 67 | // Utility method to print a card's information 68 | public static void printSummary(CreditCard card) { 69 | System.out.println("Customer = " + card.customer); 70 | System.out.println("Bank = " + card.bank); 71 | System.out.println("Account = " + card.account); 72 | System.out.println("Balance = " + card.balance); 73 | System.out.println("Limit = " + card.limit); 74 | } 75 | 76 | public static void main(String[] args) { 77 | CreditCard[] wallet = new CreditCard[3]; 78 | wallet[0] = new CreditCard("John Bowman", "California Savings", "5391 0375 9387 5309", 5000); 79 | wallet[1] = new CreditCard("John Bowman", "California Federal", "3485 0399 3395 1954", 3500); 80 | wallet[2] = new CreditCard("John Bowman", "California Finance", "5391 0375 9387 5309", 2500, 300); 81 | 82 | for (int val = 1; val <= 16; val++) { 83 | wallet[0].charge(3 * val); 84 | wallet[1].charge(2 * val); 85 | wallet[2].charge(val); 86 | } 87 | 88 | for (CreditCard card : wallet) { 89 | CreditCard.printSummary(card); // calling static method 90 | while (card.getBalance() > 200.0) { 91 | card.makePayment(200); 92 | System.out.println("New balance = " + card.getBalance()); 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ch02/src/main/java/CreditCard.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This {@code CreditCard} class defines credit card objects that model a simplified version of traditional credit cards. 3 | * They store information about the customer, issuing bank, account identifier, credit limit, and current balance. They 4 | * do not charge interest or late payments, but they do restrict charges that would cause a card's balance to go over its 5 | * credit limit. 6 | */ 7 | public class CreditCard { 8 | 9 | // Instance variables: 10 | private String customer; // name of the customer (e.g., "John Bowman") 11 | private String bank; // name of the bank (e.g., "California Savings") 12 | private String account; // account identifier (e.g., "5391 0375 9387 5309") 13 | private int limit; // credit limit (measure in dollars) 14 | protected double balance; // current balance (measure in dollars) 15 | //private double balance; // current balance (measure in dollars) 16 | 17 | // Constructors: 18 | public CreditCard(String customer, String bank, String account, int limit, double balance) { 19 | this.customer = customer; 20 | this.bank = bank; 21 | this.account = account; 22 | this.limit = limit; 23 | this.balance = balance; 24 | } 25 | 26 | public CreditCard(String customer, String bank, String account, int limit) { 27 | this(customer, bank, account, limit, 0.0); 28 | } 29 | 30 | public CreditCard() { 31 | 32 | } 33 | 34 | // Accessor methods: 35 | public String getCustomer() { 36 | return customer; 37 | } 38 | 39 | public String getBank() { 40 | return bank; 41 | } 42 | 43 | public String getAccount() { 44 | return account; 45 | } 46 | 47 | public int getLimit() { 48 | return limit; 49 | } 50 | 51 | public double getBalance() { 52 | return balance; 53 | } 54 | 55 | // Update methods: 56 | public boolean charge(double price) { 57 | if (price + balance > limit) { 58 | return false; 59 | } 60 | balance += price; 61 | return true; 62 | } 63 | 64 | public void makePayment(double amount) { 65 | balance -= amount; 66 | } 67 | 68 | // Utility method to print a card's information 69 | public static void printSummary(CreditCard card) { 70 | System.out.println("Customer = " + card.customer); 71 | System.out.println("Bank = " + card.bank); 72 | System.out.println("Account = " + card.account); 73 | System.out.println("Balance = " + card.balance); 74 | System.out.println("Limit = " + card.limit); 75 | } 76 | 77 | public static void main(String[] args) { 78 | CreditCard[] wallet = new CreditCard[3]; 79 | wallet[0] = new CreditCard("John Bowman", "California Savings", "5391 0375 9387 5309", 5000); 80 | wallet[1] = new CreditCard("John Bowman", "California Federal", "3485 0399 3395 1954", 3500); 81 | wallet[2] = new CreditCard("John Bowman", "California Finance", "5391 0375 9387 5309", 2500, 300); 82 | 83 | for (int val = 1; val <= 16; val++) { 84 | wallet[0].charge(3 * val); 85 | wallet[1].charge(2 * val); 86 | wallet[2].charge(val); 87 | } 88 | 89 | for (CreditCard card : wallet) { 90 | CreditCard.printSummary(card); // calling static method 91 | while (card.getBalance() > 200.0) { 92 | card.makePayment(200); 93 | System.out.println("New balance = " + card.getBalance()); 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /ch04/src/main/java/StringExperiment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | /** 25 | * Provides an empirical test of the efficiency of repeated string concatentation 26 | * versus use of the StringBuilder class. 27 | * 28 | * @author Michael T. Goodrich 29 | * @author Roberto Tamassia 30 | * @author Michael H. Goldwasser 31 | */ 32 | public class StringExperiment { 33 | 34 | /** Uses repeated concatenation to compose a String with n copies of character c. */ 35 | public static String repeat1(char c, int n) { 36 | String answer = ""; 37 | for (int j=0; j < n; j++) 38 | answer += c; 39 | return answer; 40 | } 41 | 42 | /** Uses StringBuilder to compose a String with n copies of character c. */ 43 | public static String repeat2(char c, int n) { 44 | StringBuilder sb = new StringBuilder(); 45 | for (int j=0; j < n; j++) 46 | sb.append(c); 47 | return sb.toString(); 48 | } 49 | 50 | /** 51 | * Tests the two versions of the 'repeat' algorithm, doubling the 52 | * size of n each trial, beginning with the given start value. The 53 | * first command line argument can be used to change the number of 54 | * trials, and the second to adjust the start value. 55 | */ 56 | public static void main(String[] args) { 57 | int n = 50000; // starting value 58 | int trials = 10; 59 | try { 60 | if (args.length > 0) 61 | trials = Integer.parseInt(args[0]); 62 | if (args.length > 1) 63 | n = Integer.parseInt(args[1]); 64 | } catch (NumberFormatException e) { } 65 | int start = n; // remember the original starting value 66 | 67 | // let's run version 2 (the quicker one) first 68 | System.out.println("Testing repeat2..."); 69 | for (int t=0; t < trials; t++) { 70 | long startTime = System.currentTimeMillis(); 71 | String temp = repeat2('-', n); 72 | long endTime = System.currentTimeMillis(); 73 | long elapsed = endTime - startTime; 74 | System.out.println(String.format("n: %9d took %12d milliseconds", n, elapsed)); 75 | n *= 2; // double the problem size 76 | } 77 | 78 | System.out.println("Testing repeat1..."); 79 | n = start; // restore n to its start value 80 | for (int t=0; t < trials; t++) { 81 | long startTime = System.currentTimeMillis(); 82 | String temp = repeat1('-', n); 83 | long endTime = System.currentTimeMillis(); 84 | long elapsed = endTime - startTime; 85 | System.out.println(String.format("n: %9d took %12d milliseconds", n, elapsed)); 86 | n *= 2; // double the problem size 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ch03/src/main/java/DoublyLinkedList.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A basic doubly linked list implementation. 3 | */ 4 | public class DoublyLinkedList { 5 | 6 | private static class Node { 7 | private E element; 8 | private Node prev; 9 | private Node next; 10 | 11 | public Node(E e, Node p, Node n) { 12 | element = e; 13 | prev = p; 14 | next = n; 15 | } 16 | 17 | public E getElement() { 18 | return element; 19 | } 20 | 21 | public Node getPrev() { 22 | return prev; 23 | } 24 | 25 | public Node getNext() { 26 | return next; 27 | } 28 | 29 | public void setPrev(Node p) { 30 | prev = p; 31 | } 32 | 33 | public void setNext(Node n) { 34 | next = n; 35 | } 36 | } // end of nested Node class 37 | 38 | // instance variables of the DoublyLinkedList 39 | private Node header; 40 | private Node trailer; 41 | private int size = 0; 42 | 43 | /** 44 | * Constructs a new empty list. 45 | */ 46 | public DoublyLinkedList() { 47 | header = new Node<>(null, null, null); 48 | trailer = new Node<>(null, header, null); 49 | header.setNext(trailer); 50 | } 51 | 52 | /** 53 | * Returns the number of elements in the linked list. 54 | * 55 | * @return 返回链表长度 56 | */ 57 | public int size() { 58 | return size; 59 | } 60 | 61 | public boolean isEmpty() { 62 | return size == 0; 63 | } 64 | 65 | public E first() { 66 | if (isEmpty()) return null; 67 | return header.getNext().getElement(); 68 | } 69 | 70 | /** 71 | * @return the last element 72 | */ 73 | public E last() { 74 | if (isEmpty()) return null; 75 | return trailer.getPrev().getElement(); 76 | } 77 | 78 | // public update methods 79 | 80 | /** 81 | * Adds element e to the front of the list. 82 | */ 83 | public void addFirst(E e) { 84 | addBetween(e, header, header.getNext()); 85 | } 86 | 87 | /** 88 | * Adds element e to the end of the list. 89 | * 90 | * @param e element added to the end of the list. 91 | */ 92 | public void addLast(E e) { 93 | addBetween(e, trailer.getPrev(), trailer); 94 | } 95 | 96 | /** 97 | * Removes and returns the first element of the list. 98 | * 99 | * @return e the removed element 100 | */ 101 | public E removeFirst() { 102 | if (isEmpty()) return null; 103 | return remove(header.getNext()); 104 | } 105 | 106 | /** 107 | * Removes and returns the last element of the list. 108 | * 109 | * @return the removed element. 110 | */ 111 | public E removeLast() { 112 | if (isEmpty()) return null; 113 | return remove(trailer.getPrev()); 114 | } 115 | 116 | private void addBetween(E e, Node predecessor, Node successor) { 117 | // create and link a new node 118 | Node newest = new Node<>(e, predecessor, successor); 119 | predecessor.setNext(newest); 120 | successor.setPrev(newest); 121 | size++; 122 | } 123 | 124 | private E remove(Node node) { 125 | Node predecessor = node.getPrev(); 126 | Node successor = node.getNext(); 127 | predecessor.setNext(successor); 128 | successor.setPrev(predecessor); 129 | size--; 130 | return node.getElement(); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /ch08/src/main/java/TraversalExamples.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | public class TraversalExamples { 3 | 4 | /** Returns a string containing n spaces. */ 5 | public static String spaces(int n) { 6 | return StringExperiment.repeat2(' ', n); 7 | } 8 | 9 | public static void printPreorder(AbstractTree T) { 10 | for (Position p : T.preorder()) 11 | System.out.println(p.getElement()); 12 | } 13 | 14 | public static void printPreorderIndentSlow(AbstractTree T) { 15 | for (Position p : T.preorder()) 16 | System.out.println(spaces(2*T.depth(p)) + p.getElement()); // beware of inefficiency 17 | } 18 | 19 | /** Prints preorder representation of subtree of T rooted at p having depth d. */ 20 | public static void printPreorderIndent(Tree T, Position p, int d) { 21 | System.out.println(spaces(2*d) + p.getElement()); // indent based on d 22 | for (Position c : T.children(p)) 23 | printPreorderIndent(T, c, d+1); // child depth is d+1 24 | } 25 | 26 | /** Prints labeled representation of subtree of T rooted at p having depth d. */ 27 | public static 28 | void printPreorderLabeled(Tree T, Position p, ArrayList path) { 29 | int d = path.size(); // depth equals the length of the path 30 | System.out.print(spaces(2*d)); // print indentation, then label 31 | for (int j=0; j < d; j++) System.out.print(path.get(j) + (j == d-1 ? " " : ".")); 32 | System.out.println(p.getElement()); 33 | path.add(1); // add path entry for first child 34 | for (Position c : T.children(p)) { 35 | printPreorderLabeled(T, c, path); 36 | path.set(d, 1 + path.get(d)); // increment last entry of path 37 | } 38 | path.remove(d); // restore path to its incoming state 39 | } 40 | 41 | /** Prints parenthesized representation of subtree of T rooted at p. */ 42 | public static void parenthesize(Tree T, Position p) { 43 | System.out.print(p.getElement()); 44 | if (T.isInternal(p)) { 45 | boolean firstTime = true; 46 | for (Position c : T.children(p)) { 47 | System.out.print( (firstTime ? " (" : ", ") ); // determine proper punctuation 48 | firstTime = false; // any future passes will get comma 49 | parenthesize(T, c); // recur on child 50 | } 51 | System.out.print(")"); 52 | } 53 | } 54 | 55 | /** Returns total disk space for subtree of T rooted at p. */ 56 | public static int diskSpace(Tree T, Position p) { 57 | int subtotal = p.getElement(); // we assume element represents space usage 58 | for (Position c : T.children(p)) 59 | subtotal += diskSpace(T, c); 60 | return subtotal; 61 | } 62 | 63 | 64 | // fake interface for geometric layout problem 65 | public interface Geometric { 66 | public void setX(int x); 67 | public void setY(int y); 68 | } 69 | 70 | /** Defines geometry for an inorder layout of subtree of a binary tree. */ 71 | public static int layout(BinaryTree T, Position p, int d, int x) { 72 | if (T.left(p) != null) 73 | x = layout(T, T.left(p), d+1, x); // resulting x will be increased 74 | p.getElement().setX(x++); // post-increment x 75 | p.getElement().setY(d); 76 | if (T.right(p) != null) 77 | x = layout(T, T.right(p), d+1, x); // resulting x will be increased 78 | return x; 79 | } 80 | 81 | public static void main(String[] args) { 82 | // Tree company = new Lin 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /ch03/src/main/java/SinglyLinkedList.java: -------------------------------------------------------------------------------- 1 | public class SinglyLinkedList implements Cloneable{ 2 | private static class Node { 3 | private E element; 4 | private Node next; 5 | 6 | public Node(E e, Node n) { 7 | element = e; 8 | next = n; 9 | } 10 | 11 | public E getElement() { 12 | return element; 13 | } 14 | 15 | public Node getNext() { 16 | return next; 17 | } 18 | 19 | public void setNext(Node n) { 20 | next = n; 21 | } 22 | } 23 | 24 | private Node head = null; 25 | private Node tail = null; 26 | private int size = 0; 27 | 28 | public SinglyLinkedList() { 29 | } 30 | 31 | public int size() { 32 | return size; 33 | } 34 | 35 | public boolean isEmpty() { 36 | return size == 0; 37 | } 38 | 39 | public E first() { 40 | if (isEmpty()) { 41 | return null; 42 | } 43 | return head.getElement(); 44 | } 45 | 46 | public E last() { 47 | if (isEmpty()) { 48 | return null; 49 | } 50 | return tail.getElement(); 51 | } 52 | 53 | // update methods 54 | public void addFirst(E e) { 55 | head = new Node<>(e, head); 56 | if (size == 0) { 57 | tail = head; 58 | } 59 | size++; 60 | } 61 | 62 | public void addLast(E e) { 63 | Node newest = new Node<>(e, null); 64 | if (isEmpty()) { 65 | head = newest; 66 | } else { 67 | tail.setNext(newest); 68 | } 69 | tail = newest; 70 | size++; 71 | } 72 | 73 | public E removeFirst() { 74 | if (isEmpty()) { 75 | return null; 76 | } 77 | E answer = head.getElement(); 78 | head = head.getNext(); 79 | size--; 80 | if (size == 0) { 81 | tail = null; 82 | } 83 | return answer; 84 | } 85 | 86 | // 重写 SinglyLinkedList 的 equals 方法 87 | @Override 88 | public boolean equals(Object obj) { 89 | if (obj == null) return false; 90 | if (getClass() != obj.getClass()) return false; 91 | SinglyLinkedList other = (SinglyLinkedList) obj; // use nonparameterized type // raw types 92 | if (size != other.size) return false; 93 | Node walkA = head; // traverse the primary list 94 | Node walkB = other.head; // traverse the secondary list 95 | while (walkA != null) { 96 | if (!walkA.getElement().equals(walkB.getElement())) return false; 97 | walkA = walkA.getNext(); 98 | walkB = walkB.getNext(); 99 | } 100 | return true; // if we reach this, everything matched successfully 101 | } 102 | 103 | // 重写 clone 方法 104 | @Override 105 | protected Object clone() throws CloneNotSupportedException { 106 | // always use inherited Object.clone() to create the initial copy 107 | SinglyLinkedList other = (SinglyLinkedList) super.clone(); // safe cast 108 | if (size > 0) { 109 | other.head = new Node<>(head.getElement(), null); 110 | Node walk = head.getNext(); 111 | Node otherTail = other.head; 112 | while (walk != null) { 113 | Node newest = new Node<>(walk.getElement(), null); 114 | otherTail.setNext(newest); 115 | otherTail = newest; 116 | walk = walk.getNext(); 117 | } 118 | } 119 | return other; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /ch06/src/main/java/SinglyLinkedList.java: -------------------------------------------------------------------------------- 1 | public class SinglyLinkedList implements Cloneable{ 2 | private static class Node { 3 | private E element; 4 | private Node next; 5 | 6 | public Node(E e, Node n) { 7 | element = e; 8 | next = n; 9 | } 10 | 11 | public E getElement() { 12 | return element; 13 | } 14 | 15 | public Node getNext() { 16 | return next; 17 | } 18 | 19 | public void setNext(Node n) { 20 | next = n; 21 | } 22 | } 23 | 24 | private Node head = null; 25 | private Node tail = null; 26 | private int size = 0; 27 | 28 | public SinglyLinkedList() { 29 | } 30 | 31 | public int size() { 32 | return size; 33 | } 34 | 35 | public boolean isEmpty() { 36 | return size == 0; 37 | } 38 | 39 | public E first() { 40 | if (isEmpty()) { 41 | return null; 42 | } 43 | return head.getElement(); 44 | } 45 | 46 | public E last() { 47 | if (isEmpty()) { 48 | return null; 49 | } 50 | return tail.getElement(); 51 | } 52 | 53 | // update methods 54 | public void addFirst(E e) { 55 | head = new Node<>(e, head); 56 | if (size == 0) { 57 | tail = head; 58 | } 59 | size++; 60 | } 61 | 62 | public void addLast(E e) { 63 | Node newest = new Node<>(e, null); 64 | if (isEmpty()) { 65 | head = newest; 66 | } else { 67 | tail.setNext(newest); 68 | } 69 | tail = newest; 70 | size++; 71 | } 72 | 73 | public E removeFirst() { 74 | if (isEmpty()) { 75 | return null; 76 | } 77 | E answer = head.getElement(); 78 | head = head.getNext(); 79 | size--; 80 | if (size == 0) { 81 | tail = null; 82 | } 83 | return answer; 84 | } 85 | 86 | // 重写 SinglyLinkedList 的 equals 方法 87 | @Override 88 | public boolean equals(Object obj) { 89 | if (obj == null) return false; 90 | if (getClass() != obj.getClass()) return false; 91 | SinglyLinkedList other = (SinglyLinkedList) obj; // use nonparameterized type // raw types 92 | if (size != other.size) return false; 93 | Node walkA = head; // traverse the primary list 94 | Node walkB = other.head; // traverse the secondary list 95 | while (walkA != null) { 96 | if (!walkA.getElement().equals(walkB.getElement())) return false; 97 | walkA = walkA.getNext(); 98 | walkB = walkB.getNext(); 99 | } 100 | return true; // if we reach this, everything matched successfully 101 | } 102 | 103 | // 重写 clone 方法 104 | @Override 105 | protected Object clone() throws CloneNotSupportedException { 106 | // always use inherited Object.clone() to create the initial copy 107 | SinglyLinkedList other = (SinglyLinkedList) super.clone(); // safe cast 108 | if (size > 0) { 109 | other.head = new Node<>(head.getElement(), null); 110 | Node walk = head.getNext(); 111 | Node otherTail = other.head; 112 | while (walk != null) { 113 | Node newest = new Node<>(walk.getElement(), null); 114 | otherTail.setNext(newest); 115 | otherTail = newest; 116 | walk = walk.getNext(); 117 | } 118 | } 119 | return other; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /ch09/src/main/java/HeapAdaptablePriorityQueue.java: -------------------------------------------------------------------------------- 1 | import java.util.Comparator; 2 | 3 | public class HeapAdaptablePriorityQueue extends HeapPriorityQueue implements AdaptablePriorityQueue { 4 | 5 | // ---------------------- nested AdaptablePQEntry class -------------------------- 6 | protected static class AdaptablePQEntry extends PQEntry { 7 | protected int index; // entry's current index with the heap 8 | 9 | public AdaptablePQEntry(K key, V value, int j) { 10 | super(key, value); // this sets the key and value 11 | index = j; // this sets the new field 12 | } 13 | 14 | public int getIndex() { 15 | return index; 16 | } 17 | 18 | public void setIndex(int j) { 19 | index = j; 20 | } 21 | } // ------------------- end of nested AdaptablePQEntry class --------------------- 22 | 23 | public HeapAdaptablePriorityQueue() { 24 | super(); 25 | } 26 | 27 | public HeapAdaptablePriorityQueue(Comparator comp) { 28 | super(comp); 29 | } 30 | 31 | // protected utilities 32 | 33 | /** 34 | * Validates an entry to ensure it is location-aware. 35 | */ 36 | protected AdaptablePQEntry validate(Entry entry) throws IllegalArgumentException { 37 | if (!(entry instanceof AdaptablePQEntry)) 38 | throw new IllegalArgumentException("Invalid entry"); 39 | AdaptablePQEntry locator = (AdaptablePQEntry) entry; // safe 40 | int j = locator.getIndex(); 41 | if (j >= heap.size() || heap.get(j) != locator) 42 | throw new IllegalArgumentException("Invalid entry"); 43 | return locator; 44 | } 45 | 46 | protected void swap(int i, int j) { 47 | super.swap(i, j); // perform the swap 48 | ((AdaptablePQEntry) heap.get(i)).setIndex(i); //reset entry's index 49 | ((AdaptablePQEntry) heap.get(j)).setIndex(j); //reset entry's index 50 | } 51 | 52 | /** 53 | * Restores the heap property by moving the entry at index j upward/downward. 54 | */ 55 | protected void bubble(int j) { 56 | if (j > 0 && compare(heap.get(j), heap.get(parent(j))) < 0) 57 | upheap(j); 58 | else 59 | downHeap(j); // although it might not need to move 60 | } 61 | 62 | public Entry insert(K key, V value) throws IllegalArgumentException { 63 | checkKey(key); 64 | Entry newest = new AdaptablePQEntry<>(key, value, heap.size()); 65 | heap.add(newest); 66 | upheap(heap.size() - 1); 67 | return newest; 68 | } 69 | 70 | public void remove(Entry entry) throws IllegalArgumentException { 71 | AdaptablePQEntry locator = validate(entry); 72 | int j = locator.getIndex(); 73 | if (j == heap.size() - 1) // entry is at last position 74 | heap.remove(heap.size() - 1); // so just remove it 75 | else { 76 | swap(j, heap.size() - 1); // swap entry to last position 77 | heap.remove(heap.size() - 1); // then remove it 78 | bubble(j); // and fix entry displaced by the swap 79 | } 80 | } 81 | 82 | public void replaceKey(Entry entry, K key) throws IllegalArgumentException { 83 | AdaptablePQEntry locator = validate(entry); 84 | checkKey(key); // might throw an exception 85 | locator.setKey(key); // method inherited from PQEntry 86 | bubble(locator.getIndex()); // with new key, may need to move entry 87 | } 88 | 89 | public void replaceValue(Entry entry, V value) throws IllegalArgumentException { 90 | AdaptablePQEntry locator = validate(entry); 91 | locator.setValue(value); // method inherited from PQEntry 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /ch10/src/main/java/SortedMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | /** 25 | * A map with additional support for keys from a total ordering. 26 | * 27 | * The total ordering is the natural ordering of keys, by default, 28 | * or it can be defined by providing an optional Comparator. 29 | * 30 | * All iterations will be in sorted order relative to the keys, 31 | * and additional methods provide for non-exact searches. 32 | * This interface is a simple variant that blends features of 33 | * java.util.SortedMap and java.util.NavigableMap. 34 | * 35 | * @author Michael T. Goodrich 36 | * @author Roberto Tamassia 37 | * @author Michael H. Goldwasser 38 | */ 39 | public interface SortedMap extends Map{ 40 | 41 | /** 42 | * Returns the entry having the least key (or null if map is empty). 43 | * @return entry with least key (or null if map is empty) 44 | */ 45 | Entry firstEntry(); 46 | 47 | /** 48 | * Returns the entry having the greatest key (or null if map is empty). 49 | * @return entry with greatest key (or null if map is empty) 50 | */ 51 | Entry lastEntry(); 52 | 53 | /** 54 | * Returns the entry with least key greater than or equal to given key 55 | * (or null if no such key exists). 56 | * @return entry with least key greater than or equal to given (or null if no such entry) 57 | * @throws IllegalArgumentException if the key is not compatible with the map 58 | */ 59 | Entry ceilingEntry(K key) throws IllegalArgumentException; 60 | 61 | /** 62 | * Returns the entry with greatest key less than or equal to given key 63 | * (or null if no such key exists). 64 | * @return entry with greatest key less than or equal to given (or null if no such entry) 65 | * @throws IllegalArgumentException if the key is not compatible with the map 66 | */ 67 | Entry floorEntry(K key) throws IllegalArgumentException; 68 | 69 | /** 70 | * Returns the entry with greatest key strictly less than given key 71 | * (or null if no such key exists). 72 | * @return entry with greatest key strictly less than given (or null if no such entry) 73 | * @throws IllegalArgumentException if the key is not compatible with the map 74 | */ 75 | Entry lowerEntry(K key) throws IllegalArgumentException; 76 | 77 | /** 78 | * Returns the entry with least key strictly greater than given key 79 | * (or null if no such key exists). 80 | * @return entry with least key strictly greater than given (or null if no such entry) 81 | * @throws IllegalArgumentException if the key is not compatible with the map 82 | */ 83 | Entry higherEntry(K key) throws IllegalArgumentException; 84 | 85 | /** 86 | * Returns an iterable containing all keys in the range from 87 | * fromKey inclusive to toKey exclusive. 88 | * @return iterable with keys in desired range 89 | * @throws IllegalArgumentException if fromKey or toKey is not compatible with the map 90 | */ 91 | Iterable> subMap(K fromKey, K toKey) throws IllegalArgumentException; 92 | } 93 | -------------------------------------------------------------------------------- /ch12/src/main/java/QuickSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | import java.util.Comparator; 25 | 26 | class QuickSort { 27 | 28 | //-------- support for top-down quick-sort of queues -------- 29 | /** Quick-sort contents of a queue. */ 30 | public static void quickSort(Queue S, Comparator comp) { 31 | int n = S.size(); 32 | if (n < 2) return; // queue is trivially sorted 33 | // divide 34 | K pivot = S.first(); // using first as arbitrary pivot 35 | Queue L = new LinkedQueue<>(); 36 | Queue E = new LinkedQueue<>(); 37 | Queue G = new LinkedQueue<>(); 38 | while (!S.isEmpty()) { // divide original into L, E, and G 39 | K element = S.dequeue(); 40 | int c = comp.compare(element, pivot); 41 | if (c < 0) // element is less than pivot 42 | L.enqueue(element); 43 | else if (c == 0) // element is equal to pivot 44 | E.enqueue(element); 45 | else // element is greater than pivot 46 | G.enqueue(element); 47 | } 48 | // conquer 49 | quickSort(L, comp); // sort elements less than pivot 50 | quickSort(G, comp); // sort elements greater than pivot 51 | // concatenate results 52 | while (!L.isEmpty()) 53 | S.enqueue(L.dequeue()); 54 | while (!E.isEmpty()) 55 | S.enqueue(E.dequeue()); 56 | while (!G.isEmpty()) 57 | S.enqueue(G.dequeue()); 58 | } 59 | 60 | //-------- support for in-place quick-sort of an array -------- 61 | /** Quick-sort contents of a queue. */ 62 | public static void quickSortInPlace(K[] S, Comparator comp) { 63 | quickSortInPlace(S, comp, 0, S.length-1); 64 | } 65 | 66 | /** Sort the subarray S[a..b] inclusive. */ 67 | private static void quickSortInPlace(K[] S, Comparator comp, 68 | int a, int b) { 69 | if (a >= b) return; // subarray is trivially sorted 70 | int left = a; 71 | int right = b-1; 72 | K pivot = S[b]; 73 | K temp; // temp object used for swapping 74 | while (left <= right) { 75 | // scan until reaching value equal or larger than pivot (or right marker) 76 | while (left <= right && comp.compare(S[left], pivot) < 0) left++; 77 | // scan until reaching value equal or smaller than pivot (or left marker) 78 | while (left <= right && comp.compare(S[right], pivot) > 0) right--; 79 | if (left <= right) { // indices did not strictly cross 80 | // so swap values and shrink range 81 | temp = S[left]; S[left] = S[right]; S[right] = temp; 82 | left++; right--; 83 | } 84 | } 85 | // put pivot into its final place (currently marked by left index) 86 | temp = S[left]; S[left] = S[b]; S[b] = temp; 87 | // make recursive calls 88 | quickSortInPlace(S, comp, a, left - 1); 89 | quickSortInPlace(S, comp, left + 1, b); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # This file is inspired by https://github.com/alexkaratarakis/gitattributes 2 | # 3 | # Auto detect text files and perform LF normalization 4 | # http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/ 5 | * text=auto 6 | 7 | # The above will handle all files NOT found below 8 | # These files are text and should be normalized (Convert crlf => lf) 9 | 10 | *.bat text eol=crlf 11 | *.coffee text 12 | *.css text 13 | *.cql text 14 | *.df text 15 | *.ejs text 16 | *.html text 17 | *.java text 18 | *.js text 19 | *.json text 20 | *.less text 21 | *.properties text 22 | *.sass text 23 | *.scss text 24 | *.sh text eol=lf 25 | *.sql text 26 | *.txt text 27 | *.ts text 28 | *.xml text 29 | *.yaml text 30 | *.yml text 31 | 32 | # Documents 33 | *.doc diff=astextplain 34 | *.DOC diff=astextplain 35 | *.docx diff=astextplain 36 | *.DOCX diff=astextplain 37 | *.dot diff=astextplain 38 | *.DOT diff=astextplain 39 | *.pdf diff=astextplain 40 | *.PDF diff=astextplain 41 | *.rtf diff=astextplain 42 | *.RTF diff=astextplain 43 | *.markdown text 44 | *.md text 45 | *.adoc text 46 | *.textile text 47 | *.mustache text 48 | *.csv text 49 | *.tab text 50 | *.tsv text 51 | *.txt text 52 | AUTHORS text 53 | CHANGELOG text 54 | CHANGES text 55 | CONTRIBUTING text 56 | COPYING text 57 | copyright text 58 | *COPYRIGHT* text 59 | INSTALL text 60 | license text 61 | LICENSE text 62 | NEWS text 63 | readme text 64 | *README* text 65 | TODO text 66 | 67 | # Graphics 68 | *.png binary 69 | *.jpg binary 70 | *.jpeg binary 71 | *.gif binary 72 | *.tif binary 73 | *.tiff binary 74 | *.ico binary 75 | # SVG treated as an asset (binary) by default. If you want to treat it as text, 76 | # comment-out the following line and uncomment the line after. 77 | *.svg binary 78 | #*.svg text 79 | *.eps binary 80 | 81 | # These files are binary and should be left untouched 82 | # (binary is a macro for -text -diff) 83 | *.class binary 84 | *.jar binary 85 | *.war binary 86 | 87 | ## LINTERS 88 | .csslintrc text 89 | .eslintrc text 90 | .jscsrc text 91 | .jshintrc text 92 | .jshintignore text 93 | .stylelintrc text 94 | 95 | ## CONFIGS 96 | *.conf text 97 | *.config text 98 | .editorconfig text 99 | .gitattributes text 100 | .gitconfig text 101 | .gitignore text 102 | .htaccess text 103 | *.npmignore text 104 | 105 | ## HEROKU 106 | Procfile text 107 | .slugignore text 108 | 109 | ## AUDIO 110 | *.kar binary 111 | *.m4a binary 112 | *.mid binary 113 | *.midi binary 114 | *.mp3 binary 115 | *.ogg binary 116 | *.ra binary 117 | 118 | ## VIDEO 119 | *.3gpp binary 120 | *.3gp binary 121 | *.as binary 122 | *.asf binary 123 | *.asx binary 124 | *.fla binary 125 | *.flv binary 126 | *.m4v binary 127 | *.mng binary 128 | *.mov binary 129 | *.mp4 binary 130 | *.mpeg binary 131 | *.mpg binary 132 | *.swc binary 133 | *.swf binary 134 | *.webm binary 135 | 136 | ## ARCHIVES 137 | *.7z binary 138 | *.gz binary 139 | *.rar binary 140 | *.tar binary 141 | *.zip binary 142 | 143 | ## FONTS 144 | *.ttf binary 145 | *.eot binary 146 | *.otf binary 147 | *.woff binary 148 | *.woff2 binary 149 | -------------------------------------------------------------------------------- /ch08/src/main/java/AbstractTree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * An abstract base class providing some functionality of the Tree interface. 3 | */ 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public abstract class AbstractTree implements Tree { 9 | 10 | @Override 11 | public boolean isInternal(Position p) throws IllegalArgumentException { 12 | return numChildren(p) > 0; 13 | } 14 | 15 | @Override 16 | public boolean isExternal(Position p) throws IllegalArgumentException { 17 | return numChildren(p) == 0; 18 | } 19 | 20 | @Override 21 | public boolean isRoot(Position p) throws IllegalArgumentException { 22 | return p == root(); 23 | } 24 | 25 | @Override 26 | public boolean isEmpty() { 27 | return size() == 0; 28 | } 29 | 30 | /** 31 | * @param p the position 32 | * @return the number of levels separating Position p from the root. 33 | */ 34 | public int depth(Position p) { 35 | if (isRoot(p)) 36 | return 0; 37 | else 38 | return 1 + depth(parent(p)); 39 | } 40 | 41 | /** 42 | * @return Returns the height of the tree. 43 | */ 44 | private int heightBad() { // works, but quadratic worst-case time. 可以用,但是最坏情况是平方阶 45 | int h = 0; 46 | for (Position p : positions()) 47 | if (isExternal(p)) // only consider leaf positions 48 | h = Math.max(h, depth(p)); 49 | return h; 50 | } 51 | 52 | /** 53 | * @param p position where the subtree rooted 54 | * @return the height of the subtree rooted at Position p. 55 | */ 56 | public int height(Position p) { 57 | int h = 0; // base case if p is external 58 | for (Position c : children(p)) 59 | h = Math.max(h, 1 + height(c)); 60 | return h; 61 | } 62 | 63 | /** 64 | * Adds positions of the subtree rooted at Position p to the given snapshot. 65 | * 66 | * @param p position 67 | * @param snapshot snapshot 68 | */ 69 | private void preorderSubtree(Position p, List> snapshot) { // 这个 List 也是 java.util.List; 70 | snapshot.add(p); 71 | for (Position c : children(p)) 72 | preorderSubtree(c, snapshot); 73 | } 74 | 75 | /** 76 | * @return an iterable collection of positions of the tree, reported in preorder. 77 | */ 78 | public Iterable> preorder() { 79 | List> snapshot = new ArrayList<>(); 80 | if (!isEmpty()) 81 | preorderSubtree(root(), snapshot); // fill the snapshot recursively 82 | return snapshot; 83 | } 84 | 85 | /** 86 | * Adds positions of the subtree rooted at Position p to the given snapshot. 87 | */ 88 | private void postorderSubtree(Position p, List> snapshot) { 89 | for (Position c : children(p)) 90 | postorderSubtree(c, snapshot); 91 | snapshot.add(p); // for postorder, we add position p after exploring subtrees 92 | } 93 | 94 | /** 95 | * Returns an iterable collection of positions of the tree, reported in postorder. 96 | */ 97 | public Iterable> postorder() { 98 | List> snapshot = new ArrayList<>(); 99 | if (!isEmpty()) 100 | postorderSubtree(root(), snapshot); // fill the snapshot recursively 101 | return snapshot; 102 | } 103 | 104 | public Iterable> breadthfirst() { 105 | List> snapshot = new ArrayList<>(); 106 | if (!isEmpty()) { 107 | Queue> fringe = new LinkedQueue<>(); 108 | fringe.enqueue(root()); // start with the root 109 | while (!fringe.isEmpty()) { 110 | Position p = fringe.dequeue(); // remove from front of the queue 111 | snapshot.add(p); // report this position 112 | for (Position c : children(p)) 113 | fringe.enqueue(c); // add children to back of queue 114 | } 115 | } 116 | return snapshot; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /ch07/src/main/java/FavoritesList.java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | 3 | /** 4 | * Maintains a list of elements ordered according to access frequency. 5 | */ 6 | public class FavoritesList { 7 | //----------------- nested Item class ------------------------ 8 | protected static class Item { 9 | private E value; 10 | private int count = 0; 11 | 12 | /** 13 | * Constructs new item with initial count of zero. 14 | */ 15 | public Item(E val) { 16 | value = val; 17 | } 18 | 19 | public int getCount() { 20 | return count; 21 | } 22 | 23 | public E getValue() { 24 | return value; 25 | } 26 | 27 | public void increment() { 28 | count++; 29 | } 30 | } // ---------------- end of nested Item class ----------------- 31 | 32 | PositionalList> list = new LinkedPositionalList<>(); // list of items 33 | 34 | public FavoritesList() { // constructs initially empty favorites list 35 | } 36 | 37 | // nonpublic utilities 38 | 39 | /** 40 | * Provides shorthand notation to retrieve user's element stored at Position p. 41 | */ 42 | protected E value(Position> p) { 43 | return p.getElement().getValue(); 44 | } 45 | 46 | /** 47 | * Provides shorthand notation to retrieve count of item stored at Position p. 48 | */ 49 | protected int count(Position> p) { 50 | return p.getElement().getCount(); 51 | } 52 | 53 | /** 54 | * Returns Position having element equal to e (or null if not found) 55 | * 56 | * @param e element to find 57 | * @return element equal to e 58 | */ 59 | protected Position> findPosition(E e) { 60 | Position> walk = list.first(); 61 | while (walk != null && !e.equals(value(walk))) 62 | walk = list.after(walk); 63 | return walk; 64 | } 65 | 66 | /** 67 | * Moves item at Position p earlier in the list based on access count. 68 | * 69 | * @param p position to be moved 70 | */ 71 | protected void moveUp(Position> p) { 72 | int cnt = count(p); //revised count of accessed item 73 | Position> walk = p; 74 | while (walk != list.first() && count(list.before(walk)) < cnt) 75 | walk = list.before(walk); // found smaller count ahead of item 76 | if (walk != p) 77 | list.addBefore(walk, list.remove(p)); // remove/reinsert item 78 | } 79 | 80 | // public methods 81 | 82 | /** 83 | * @return the number of items in the favorites list. 84 | */ 85 | public int size() { 86 | return list.size(); 87 | } 88 | 89 | /** 90 | * @return true if the favorites list is empty. 91 | */ 92 | public boolean isEmpty() { 93 | return list.isEmpty(); 94 | } 95 | 96 | /** 97 | * Accesses element e (possibly new), increasing its access count. 98 | */ 99 | public void access(E e) { 100 | Position> p = findPosition(e); // try to locate existing element 101 | if (p == null) 102 | p = list.addLast(new Item(e)); // if new, place at end 103 | p.getElement().increment(); // always increment count 104 | moveUp(p); // consider moving forward 105 | } 106 | 107 | /** 108 | * Removes element equal to e from the list of favorites (if found). 109 | */ 110 | public void remove(E e) { 111 | Position> p = findPosition(e); // try to locate existing element. 112 | if (p != null) 113 | list.remove(p); 114 | } 115 | 116 | /** 117 | * Returns an iterable collection of the k most frequently accessed elements. 118 | * 119 | * @param k frequency 120 | * @return an iterable collection 121 | * @throws IllegalArgumentException if goes wrong. 122 | */ 123 | public Iterable getFavorites(int k) throws IllegalArgumentException { 124 | if (k < 0 || k > size()) 125 | throw new IllegalArgumentException("Invalid k"); 126 | PositionalList result = new LinkedPositionalList<>(); 127 | Iterator> iter = list.iterator(); 128 | for (int j = 0; j < k; j++) 129 | result.addLast(iter.next().getValue()); 130 | return result; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /ch05/src/main/java/AnalyzingRecursion.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Various recursion demos 3 | */ 4 | public class AnalyzingRecursion { 5 | 6 | 7 | /** 8 | * Returns the sum of the first n integers of the given array. 9 | */ 10 | public static int linearSum(int[] data, int n) { 11 | if (n == 0) 12 | return 0; 13 | else 14 | return linearSum(data, n - 1) + data[n - 1]; 15 | } 16 | 17 | /** 18 | * Reverses the contents of subarray data[low] through data[high] inclusive. 19 | */ 20 | public static void reverseArray(int[] data, int low, int high) { 21 | if (low < high) { 22 | int temp = data[low]; 23 | data[low] = data[high]; 24 | data[high] = temp; 25 | reverseArray(data, low + 1, high - 1); 26 | } 27 | } 28 | 29 | /** 30 | * Computes the value of x raised to the nth power, for nonnegative integer n. 31 | * 32 | * @param x 33 | * @param n 34 | * @return nth power of x. 35 | */ 36 | public static double power(double x, int n) { 37 | if (n == 0) 38 | return 1; 39 | else 40 | return x * power(x, n - 1); 41 | } 42 | 43 | public static double powerImproved(double x, int n) { 44 | if (n == 0) 45 | return 1; 46 | else { 47 | double partial = power(x, n / 2); 48 | double result = partial * partial; 49 | if (n % 2 == 1) 50 | result *= x; 51 | return result; 52 | } 53 | } 54 | 55 | 56 | /** 57 | * Returns the sum of subarray data[low] through data[high] inclusive. Binary Recursion 58 | * 59 | * @param data 60 | * @param low 61 | * @param high 62 | * @return sum 63 | */ 64 | public static int binarySum(int[] data, int low, int high) { 65 | if (low > high) 66 | return 0; 67 | else if (low == high) 68 | return data[low]; 69 | else { 70 | int mid = (low + high) / 2; 71 | return binarySum(data, low, mid) + binarySum(data, mid + 1, high); 72 | } 73 | } 74 | 75 | /** 76 | * Recursion Run Amok 77 | * Returns true if there are no duplicate values from data[low] through data[high]. 78 | */ 79 | public static boolean unique3(int[] data, int low, int high) { 80 | if (low > high) return true; // at most ont item 81 | else if (!unique3(data, low, high - 1)) return false; // duplicate in first n - 1 82 | else if (!unique3(data, low + 1, high)) return false; // duplicate in last n - 1 83 | else return (data[low] != data[high]); // do first and last differ? 84 | } 85 | 86 | /** 87 | * Returns teh nth Fibonacci number (inefficiently). 88 | */ 89 | public static long fibonacciBad(int n) { 90 | if (n <= 1) 91 | return n; 92 | else 93 | return fibonacciBad(n - 2) + fibonacciBad(n - 1); 94 | } 95 | 96 | 97 | /** 98 | * Returns arrays containing the pair of Fibonacci numbers, F(n) and F(n - 1). 99 | */ 100 | public static long[] fibonacciGood(int n) { 101 | if (n < 1) { 102 | long[] answer = {n, 0}; 103 | return answer; 104 | } else { 105 | long[] temp = fibonacciGood(n - 1); // returns { Fn-1, Fn-2} 106 | long[] answer = {temp[0] + temp[1], temp[0]}; // we want {Fn, Fn-1} 107 | return answer; 108 | } 109 | } 110 | 111 | /** 112 | * Don't call this (infinite) version. 113 | */ 114 | public static int fibonacci(int n) { 115 | return fibonacci(n); 116 | } 117 | 118 | 119 | /** 120 | * Returns true if the target value is found in the data array. 121 | */ 122 | public static boolean binarySearchIterative(int[] data, int target) { 123 | int low = 0; 124 | int high = data.length - 1; 125 | while (low < high) { 126 | int mid = (low + high) / 2; 127 | if (target == data[mid]) // found a match 128 | return true; 129 | else if (target < data[mid]) 130 | high = mid - 1; // only consider values right of mid 131 | else 132 | low = mid + 1; // only consider values right of mid 133 | } 134 | return false; // loop ended without success. 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /ch09/src/main/java/HeapPriorityQueue.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Comparator; 3 | 4 | public class HeapPriorityQueue extends AbstractPriorityQueue { 5 | protected ArrayList> heap = new ArrayList<>(); 6 | 7 | public HeapPriorityQueue() { 8 | super(); 9 | } 10 | 11 | public HeapPriorityQueue(Comparator comp) { 12 | super(comp); 13 | } 14 | 15 | public HeapPriorityQueue(K[] keys, V[] values) { 16 | super(); 17 | for (int j = 0; j < Math.min(keys.length, values.length); j++) { 18 | heap.add(new PQEntry<>(keys[j], values[j])); 19 | heapify(); 20 | } 21 | } 22 | 23 | private void heapify() { 24 | int startIndex = parent(size() - 1); // start at PARENT of last entry 25 | for (int j = startIndex; j >= 0; j--) 26 | downHeap(j); 27 | } 28 | 29 | // protected utilities 30 | protected int parent(int j) { 31 | return (j - 1) / 2; // truncating division 32 | } 33 | 34 | protected int left(int j) { 35 | return 2 * j + 1; 36 | } 37 | 38 | protected int right(int j) { 39 | return 2 * j + 2; 40 | } 41 | 42 | protected boolean hasLeft(int j) { 43 | return left(j) < heap.size(); 44 | } 45 | 46 | protected boolean hasRight(int j) { 47 | return right(j) < heap.size(); 48 | } 49 | 50 | /** 51 | * Exchanges the entries at indices i and j of the array list. 52 | */ 53 | protected void swap(int i, int j) { 54 | Entry temp = heap.get(i); 55 | heap.set(i, heap.get(j)); 56 | heap.set(j, temp); 57 | } 58 | 59 | /** 60 | * Moves the entry at index j higher, if necessary, to restore the heap property. 61 | */ 62 | protected void upheap(int j) { 63 | while (j > 0) { // continue until reaching root (or break statement) 64 | int p = parent(j); 65 | if (compare(heap.get(j), heap.get(p)) > 0) break; // heap property verified 66 | swap(j, p); 67 | j = p; // continue from the parent's location 68 | } 69 | } 70 | 71 | /** 72 | * Moves the entry at index j lower, if necessary, to restore the heap property. 73 | */ 74 | protected void downHeap(int j) { 75 | while (hasLeft(j)) { // continue to bottom (or break statement) 76 | int leftIndex = left(j); 77 | int smallChildIndex = leftIndex; // although right may be smaller 78 | if (hasRight(j)) { 79 | int rightIndex = right(j); 80 | if (compare(heap.get(smallChildIndex), heap.get(rightIndex)) > 0) 81 | smallChildIndex = rightIndex; // right child is smaller 82 | } 83 | if (compare(heap.get(smallChildIndex), heap.get(j)) >= 0) 84 | break; // heap property has been restored 85 | swap(j, smallChildIndex); 86 | j = smallChildIndex; 87 | } 88 | } 89 | 90 | // public methods 91 | @Override 92 | public int size() { 93 | return heap.size(); 94 | } 95 | 96 | @Override 97 | public Entry insert(K key, V value) throws IllegalArgumentException { 98 | checkKey(key); // auxiliary key-checking method (cloud throw exception) 99 | Entry newest = new PQEntry<>(key, value); 100 | heap.add(newest); 101 | upheap(heap.size() - 1); 102 | return newest; 103 | } 104 | 105 | @Override 106 | public Entry min() { 107 | if (heap.isEmpty()) return null; 108 | return heap.get(0); 109 | } 110 | 111 | @Override 112 | public Entry removeMin() { 113 | if (heap.isEmpty()) return null; 114 | Entry answer = heap.get(0); 115 | swap(0, heap.size() - 1); 116 | heap.remove(heap.size() - 1); 117 | downHeap(0); 118 | return answer; 119 | } 120 | 121 | 122 | /** 123 | * Sorts sequence S, using initially empty priority queue P to produce the order. 124 | */ 125 | public static void pqSort(PositionalList S, PriorityQueue P) { 126 | int n = S.size(); 127 | for (int j = 0; j < n; j++) { 128 | E element = S.remove(S.first()); 129 | P.insert(element, null); // element is key; null value 130 | } 131 | for (int j = 0; j < n; j++) { 132 | E element = P.removeMin().getKey(); 133 | S.addLast(element); // the smallest key in P is next placed in S 134 | } 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /ch14/src/main/java/Graph.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | /** 25 | * An interface for a graph structure. A graph can be declared as either directed or undirected. 26 | * In the case of an undirected graph, methods outgoingEdges and incomingEdges return the same collection, 27 | * and outDegree and inDegree return the same value. 28 | * 29 | * Every vertex stores an element of type V (possibly null). 30 | * Every edge stores an element of type E (possibly null). 31 | * 32 | * @author Michael T. Goodrich 33 | * @author Roberto Tamassia 34 | * @author Michael H. Goldwasser 35 | */ 36 | public interface Graph { 37 | 38 | /** Returns the number of vertices of the graph */ 39 | int numVertices(); 40 | 41 | /** Returns the number of edges of the graph */ 42 | int numEdges(); 43 | 44 | /** Returns the vertices of the graph as an iterable collection */ 45 | Iterable> vertices(); 46 | 47 | /** Returns the edges of the graph as an iterable collection */ 48 | Iterable> edges(); 49 | 50 | /** 51 | * Returns the number of edges leaving vertex v. 52 | * Note that for an undirected graph, this is the same result 53 | * returned by inDegree 54 | * @throws IllegalArgumentException if v is not a valid vertex 55 | */ 56 | int outDegree(Vertex v) throws IllegalArgumentException; 57 | 58 | /** 59 | * Returns the number of edges for which vertex v is the destination. 60 | * Note that for an undirected graph, this is the same result 61 | * returned by outDegree 62 | * @throws IllegalArgumentException if v is not a valid vertex 63 | */ 64 | int inDegree(Vertex v) throws IllegalArgumentException; 65 | 66 | /** 67 | * Returns an iterable collection of edges for which vertex v is the origin. 68 | * Note that for an undirected graph, this is the same result 69 | * returned by incomingEdges. 70 | * @throws IllegalArgumentException if v is not a valid vertex 71 | */ 72 | Iterable> outgoingEdges(Vertex v) throws IllegalArgumentException; 73 | 74 | /** 75 | * Returns an iterable collection of edges for which vertex v is the destination. 76 | * Note that for an undirected graph, this is the same result 77 | * returned by outgoingEdges. 78 | * @throws IllegalArgumentException if v is not a valid vertex 79 | */ 80 | Iterable> incomingEdges(Vertex v) throws IllegalArgumentException; 81 | 82 | /** Returns the edge from u to v, or null if they are not adjacent. */ 83 | Edge getEdge(Vertex u, Vertex v) throws IllegalArgumentException; 84 | 85 | /** 86 | * Returns the vertices of edge e as an array of length two. 87 | * If the graph is directed, the first vertex is the origin, and 88 | * the second is the destination. If the graph is undirected, the 89 | * order is arbitrary. 90 | */ 91 | Vertex[] endVertices(Edge e) throws IllegalArgumentException; 92 | 93 | /** Returns the vertex that is opposite vertex v on edge e. */ 94 | Vertex opposite(Vertex v, Edge e) throws IllegalArgumentException; 95 | 96 | /** Inserts and returns a new vertex with the given element. */ 97 | Vertex insertVertex(V element); 98 | 99 | /** 100 | * Inserts and returns a new edge between vertices u and v, storing given element. 101 | * 102 | * @throws IllegalArgumentException if u or v are invalid vertices, or if an edge already exists between u and v. 103 | */ 104 | Edge insertEdge(Vertex u, Vertex v, E element) throws IllegalArgumentException; 105 | 106 | /** Removes a vertex and all its incident edges from the graph. */ 107 | void removeVertex(Vertex v) throws IllegalArgumentException; 108 | 109 | /** Removes an edge from the graph. */ 110 | void removeEdge(Edge e) throws IllegalArgumentException; 111 | } 112 | -------------------------------------------------------------------------------- /ch11/src/main/java/AVLTreeMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | import java.util.Comparator; 25 | 26 | /** 27 | * An implementation of a sorted map using an AVL tree. 28 | * 29 | * @author Eric Zamore 30 | * @author Michael T. Goodrich 31 | * @author Roberto Tamassia 32 | * @author Michael H. Goldwasser 33 | */ 34 | public class AVLTreeMap extends TreeMap { 35 | 36 | /** 37 | * Constructs an empty map using the natural ordering of keys. 38 | */ 39 | public AVLTreeMap() { 40 | super(); 41 | } 42 | 43 | /** 44 | * Constructs an empty map using the given comparator to order keys. 45 | * 46 | * @param comp comparator defining the order of keys in the map 47 | */ 48 | public AVLTreeMap(Comparator comp) { 49 | super(comp); 50 | } 51 | 52 | /** 53 | * Returns the height of the given tree position. 54 | */ 55 | protected int height(Position> p) { 56 | return tree.getAux(p); 57 | } 58 | 59 | /** 60 | * Recomputes the height of the given position based on its children's heights. 61 | */ 62 | protected void recomputeHeight(Position> p) { 63 | tree.setAux(p, 1 + Math.max(height(left(p)), height(right(p)))); 64 | } 65 | 66 | /** 67 | * Returns whether a position has balance factor between -1 and 1 inclusive. 68 | */ 69 | protected boolean isBalanced(Position> p) { 70 | return Math.abs(height(left(p)) - height(right(p))) <= 1; 71 | } 72 | 73 | /** 74 | * Returns a child of p with height no smaller than that of the other child. 75 | */ 76 | protected Position> tallerChild(Position> p) { 77 | if (height(left(p)) > height(right(p))) return left(p); // clear winner 78 | if (height(left(p)) < height(right(p))) return right(p); // clear winner 79 | // equal height children; break tie while matching parent's orientation 80 | if (isRoot(p)) return left(p); // choice is irrelevant 81 | if (p == left(parent(p))) return left(p); // return aligned child 82 | else return right(p); 83 | } 84 | 85 | /** 86 | * Utility used to rebalance after an insert or removal operation. This traverses the 87 | * path upward from p, performing a trinode restructuring when imbalance is found, 88 | * continuing until balance is restored. 89 | */ 90 | protected void rebalance(Position> p) { 91 | int oldHeight, newHeight; 92 | do { 93 | oldHeight = height(p); // not yet recalculated if internal 94 | if (!isBalanced(p)) { // imbalance detected 95 | // perform trinode restructuring, setting p to resulting root, 96 | // and recompute new local heights after the restructuring 97 | p = restructure(tallerChild(tallerChild(p))); 98 | recomputeHeight(left(p)); 99 | recomputeHeight(right(p)); 100 | } 101 | recomputeHeight(p); 102 | newHeight = height(p); 103 | p = parent(p); 104 | } while (oldHeight != newHeight && p != null); 105 | } 106 | 107 | /** 108 | * Overrides the TreeMap rebalancing hook that is called after an insertion. 109 | */ 110 | @Override 111 | protected void rebalanceInsert(Position> p) { 112 | rebalance(p); 113 | } 114 | 115 | /** 116 | * Overrides the TreeMap rebalancing hook that is called after a deletion. 117 | */ 118 | @Override 119 | protected void rebalanceDelete(Position> p) { 120 | if (!isRoot(p)) 121 | rebalance(parent(p)); 122 | } 123 | 124 | /** 125 | * Ensure that current tree structure is valid AVL (for debug use only). 126 | */ 127 | private boolean sanityCheck() { 128 | for (Position> p : tree.positions()) { 129 | if (isInternal(p)) { 130 | if (p.getElement() == null) 131 | System.out.println("VIOLATION: Internal node has null entry"); 132 | else if (height(p) != 1 + Math.max(height(left(p)), height(right(p)))) { 133 | System.out.println("VIOLATION: AVL unbalanced node with key " + p.getElement().getKey()); 134 | dump(); 135 | return false; 136 | } 137 | } 138 | } 139 | return true; 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /ch10/src/main/java/SortedTableMap.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Comparator; 3 | 4 | public class SortedTableMap extends AbstractSortedMap { 5 | private ArrayList> table = new ArrayList<>(); 6 | 7 | public SortedTableMap() { 8 | super(); 9 | } 10 | 11 | public SortedTableMap(Comparator comp) { 12 | super(comp); 13 | } 14 | 15 | /** 16 | * Returns the smallest index for range table[low..high] inclusive storing an entry 17 | * with a key greater than or equal to k (or else index high+1, by convention). 18 | */ 19 | private int findIndex(K key, int low, int high) { 20 | if (high < low) return high + 1; // no entry qualifies 21 | int mid = (low + high) / 2; 22 | int comp = compare(key, table.get(mid)); 23 | if (comp == 0) 24 | return mid; // found exact match 25 | else if (comp < 0) 26 | return findIndex(key, low, mid - 1); // answer is left of mid (or possibly mid) 27 | else 28 | return findIndex(key, mid + 1, high); // answer is right of mid 29 | } 30 | 31 | /** 32 | * Version of findIndex that searches the entire table. 33 | */ 34 | private int findIndex(K key) { 35 | return findIndex(key, 0, table.size() - 1); 36 | } 37 | 38 | /** 39 | * Returns the number of entries in the map 40 | */ 41 | @Override 42 | public int size() { 43 | return table.size(); 44 | } 45 | 46 | /** 47 | * Returns the value associated with the specified key (or else null). 48 | */ 49 | @Override 50 | public V get(K key) { 51 | int j = findIndex(key); 52 | if (j == size() || compare(key, table.get(j)) != 0) return null; // no match 53 | return table.get(j).getValue(); 54 | } 55 | 56 | /** 57 | * Associates the given value with the given key, returning any overridden value. 58 | */ 59 | @Override 60 | public V put(K key, V value) { 61 | int j = findIndex(key); 62 | if (j < size() && compare(key, table.get(j)) == 0) // match exists 63 | return table.get(j).setValue(value); 64 | table.add(j, new MapEntry(key, value)); // otherwise new 65 | return null; 66 | } 67 | 68 | /** 69 | * Removes the entry having key k (if any) and returns its associated value. 70 | */ 71 | @Override 72 | public V remove(K key) { 73 | int j = findIndex(key); 74 | if (j == size() || compare(key, table.get(j)) != 0) return null; // no match 75 | return table.remove(j).getValue(); 76 | } 77 | 78 | /** 79 | * Utility returns the entry at index j, or else 80 | */ 81 | private Entry safeEntry(int j) { 82 | if (j < 0 || j >= table.size()) return null; 83 | return table.get(j); 84 | } 85 | 86 | /** 87 | * Returns the entry having the least key (or null if map is empty). 88 | */ 89 | @Override 90 | public Entry firstEntry() { 91 | return safeEntry(0); 92 | } 93 | 94 | /** 95 | * Returns the entry having the greatest key (or null if map is empty). 96 | */ 97 | @Override 98 | public Entry lastEntry() { 99 | return safeEntry(table.size() - 1); 100 | } 101 | 102 | /** 103 | * Returns the entry with least key greater than or equal to given key (if any). 104 | */ 105 | @Override 106 | public Entry ceilingEntry(K key) throws IllegalArgumentException { 107 | return safeEntry(findIndex(key)); 108 | } 109 | 110 | /** 111 | * Returns the entry with greatest key less than or equal to given key (if any). 112 | */ 113 | @Override 114 | public Entry floorEntry(K key) throws IllegalArgumentException { 115 | int j = findIndex(key); 116 | if (j == size() || !key.equals(table.get(j).getKey())) 117 | j--; // look one earlier (unless we had found a perfect match) 118 | return safeEntry(j); 119 | } 120 | 121 | /** 122 | * Returns the entry with greatest key strictly less than given key (if any). 123 | */ 124 | @Override 125 | public Entry lowerEntry(K key) throws IllegalArgumentException { 126 | return safeEntry(findIndex(key) - 1); // go strictly before the ceiling entry 127 | } 128 | 129 | @Override 130 | public Entry higherEntry(K key) throws IllegalArgumentException { 131 | /* 132 | * Returns the entry with least key strictly greater than given key (if any). 133 | */ 134 | int j = findIndex(key); 135 | if (j < size() && key.equals(table.get(j).getKey())) 136 | j++; // go past exact match 137 | return safeEntry(j); 138 | } 139 | 140 | // support for snapshot iterators for entrySet() and subMap() follow 141 | private Iterable> snapshot(int startIndex, K stop) { 142 | ArrayList> buffer = new ArrayList<>(); 143 | int j = startIndex; 144 | while (j < table.size() && (stop == null || compare(stop, table.get(j)) > 0)) 145 | buffer.add(table.get(j++)); 146 | return buffer; 147 | } 148 | 149 | @Override 150 | public Iterable> entrySet() { 151 | return snapshot(0, null); 152 | } 153 | 154 | 155 | @Override 156 | public Iterable> subMap(K fromKey, K toKey) throws IllegalArgumentException { 157 | return snapshot(findIndex(fromKey), toKey); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /ch13/src/main/java/PatternMatching.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | import java.util.Map; 25 | import java.util.HashMap; 26 | 27 | /* 28 | Note: we use char[] rather than String for these methods, simply to allow 29 | better readability of algorithms with the more direct syntax 30 | pattern[k] 31 | rather than the more verbose 32 | pattern.charAt(k) 33 | */ 34 | 35 | public class PatternMatching { 36 | 37 | /** Returns the lowest index at which substring pattern begins in text (or else -1).*/ 38 | public static int findBrute(char[] text, char[] pattern) { 39 | int n = text.length; 40 | int m = pattern.length; 41 | for (int i=0; i <= n - m; i++) { // try every starting index within text 42 | int k = 0; // k is index into pattern 43 | while (k < m && text[i+k] == pattern[k]) // kth character of pattern matches 44 | k++; 45 | if (k == m) // if we reach the end of the pattern, 46 | return i; // substring text[i..i+m-1] is a match 47 | } 48 | return -1; // search failed 49 | } 50 | 51 | /** Returns the lowest index at which substring pattern begins in text (or else -1).*/ 52 | public static int findBoyerMoore(char[] text, char[] pattern) { 53 | int n = text.length; 54 | int m = pattern.length; 55 | if (m == 0) return 0; // trivial search for empty string 56 | Map last = new HashMap<>(); // the 'last' map 57 | for (int i=0; i < n; i++) 58 | last.put(text[i], -1); // set -1 as default for all text characters 59 | for (int k=0; k < m; k++) 60 | last.put(pattern[k], k); // rightmost occurrence in pattern is last 61 | // start with the end of the pattern aligned at index m-1 of the text 62 | int i = m-1; // an index into the text 63 | int k = m-1; // an index into the pattern 64 | while (i < n) { 65 | if (text[i] == pattern[k]) { // a matching character 66 | if (k == 0) return i; // entire pattern has been found 67 | i--; // otherwise, examine previous 68 | k--; // characters of text/pattern 69 | } else { 70 | i += m - Math.min(k, 1 + last.get(text[i])); // case analysis for jump step 71 | k = m - 1; // restart at end of pattern 72 | } 73 | } 74 | return -1; // pattern was never found 75 | } 76 | 77 | /** Returns the lowest index at which substring pattern begins in text (or else -1).*/ 78 | public static int findKMP(char[] text, char[] pattern) { 79 | int n = text.length; 80 | int m = pattern.length; 81 | if (m == 0) return 0; // trivial search for empty string 82 | int[] fail = computeFailKMP(pattern); // computed by private utility 83 | int j = 0; // index into text 84 | int k = 0; // index into pattern 85 | while (j < n) { 86 | if (text[j] == pattern[k]) { // pattern[0..k] matched thus far 87 | if (k == m - 1) return j - m + 1; // match is complete 88 | j++; // otherwise, try to extend match 89 | k++; 90 | } else if (k > 0) 91 | k = fail[k-1]; // reuse suffix of P[0..k-1] 92 | else 93 | j++; 94 | } 95 | return -1; // reached end without match 96 | } 97 | 98 | private static int[] computeFailKMP(char[] pattern) { 99 | int m = pattern.length; 100 | int[] fail = new int[m]; // by default, all overlaps are zero 101 | int j = 1; 102 | int k = 0; 103 | while (j < m) { // compute fail[j] during this pass, if nonzero 104 | if (pattern[j] == pattern[k]) { // k + 1 characters match thus far 105 | fail[j] = k + 1; 106 | j++; 107 | k++; 108 | } else if (k > 0) // k follows a matching prefix 109 | k = fail[k-1]; 110 | else // no match found starting at j 111 | j++; 112 | } 113 | return fail; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ch12/src/main/java/MergeSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014, Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser 3 | * 4 | * Developed for use with the book: 5 | * 6 | * Data Structures and Algorithms in Java, Sixth Edition 7 | * Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | * John Wiley & Sons, 2014 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | import java.util.Arrays; 25 | import java.util.Comparator; 26 | 27 | class MergeSort { 28 | 29 | //-------- support for top-down merge-sort of arrays -------- 30 | /** Merge contents of arrays S1 and S2 into properly sized array S. */ 31 | public static void merge(K[] S1, K[] S2, K[] S, Comparator comp) { 32 | int i = 0, j = 0; 33 | while (i + j < S.length) { 34 | if (j == S2.length || (i < S1.length && comp.compare(S1[i], S2[j]) < 0)) 35 | S[i+j] = S1[i++]; // copy ith element of S1 and increment i 36 | else 37 | S[i+j] = S2[j++]; // copy jth element of S2 and increment j 38 | } 39 | } 40 | 41 | /** Merge-sort contents of array S. */ 42 | public static void mergeSort(K[] S, Comparator comp) { 43 | int n = S.length; 44 | if (n < 2) return; // array is trivially sorted 45 | // divide 46 | int mid = n/2; 47 | K[] S1 = Arrays.copyOfRange(S, 0, mid); // copy of first half 48 | K[] S2 = Arrays.copyOfRange(S, mid, n); // copy of second half 49 | // conquer (with recursion) 50 | mergeSort(S1, comp); // sort copy of first half 51 | mergeSort(S2, comp); // sort copy of second half 52 | // merge results 53 | merge(S1, S2, S, comp); // merge sorted halves back into original 54 | } 55 | 56 | //-------- support for top-down merge-sort of queues -------- 57 | /** Merge contents of sorted queues S1 and S2 into empty queue S. */ 58 | public static void merge(Queue S1, Queue S2, Queue S, 59 | Comparator comp) { 60 | while (!S1.isEmpty() && !S2.isEmpty()) { 61 | if (comp.compare(S1.first(), S2.first()) < 0) 62 | S.enqueue(S1.dequeue()); // take next element from S1 63 | else 64 | S.enqueue(S2.dequeue()); // take next element from S2 65 | } 66 | while (!S1.isEmpty()) 67 | S.enqueue(S1.dequeue()); // move any elements that remain in S1 68 | while (!S2.isEmpty()) 69 | S.enqueue(S2.dequeue()); // move any elements that remain in S2 70 | } 71 | 72 | /** Merge-sort contents of queue. */ 73 | public static void mergeSort(Queue S, Comparator comp) { 74 | int n = S.size(); 75 | if (n < 2) return; // queue is trivially sorted 76 | // divide 77 | Queue S1 = new LinkedQueue<>(); // (or any queue implementation) 78 | Queue S2 = new LinkedQueue<>(); 79 | while (S1.size() < n/2) 80 | S1.enqueue(S.dequeue()); // move the first n/2 elements to S1 81 | while (!S.isEmpty()) 82 | S2.enqueue(S.dequeue()); // move remaining elements to S2 83 | // conquer (with recursion) 84 | mergeSort(S1, comp); // sort first half 85 | mergeSort(S2, comp); // sort second half 86 | // merge results 87 | merge(S1, S2, S, comp); // merge sorted halves back into original 88 | } 89 | 90 | //-------- support for bottom-up merge-sort of arrays -------- 91 | /** Merges in[start..start+inc-1] and in[start+inc..start+2*inc-1] into out. */ 92 | public static void merge(K[] in, K[] out, Comparator comp, 93 | int start, int inc) { 94 | int end1 = Math.min(start + inc, in.length); // boundary for run 1 95 | int end2 = Math.min(start + 2 * inc, in.length); // boundary for run 2 96 | int x=start; // index into run 1 97 | int y=start+inc; // index into run 2 98 | int z=start; // index into output 99 | while (x < end1 && y < end2) 100 | if (comp.compare(in[x], in[y]) < 0) 101 | out[z++] = in[x++]; // take next from run 1 102 | else 103 | out[z++] = in[y++]; // take next from run 2 104 | if (x < end1) System.arraycopy(in, x, out, z, end1 - x); // copy rest of run 1 105 | else if (y < end2) System.arraycopy(in, y, out, z, end2 - y); // copy rest of run 2 106 | } 107 | 108 | @SuppressWarnings({"unchecked"}) 109 | /** Merge-sort contents of data array. */ 110 | public static void mergeSortBottomUp(K[] orig, Comparator comp) { 111 | int n = orig.length; 112 | K[] src = orig; // alias for the original 113 | K[] dest = (K[]) new Object[n]; // make a new temporary array 114 | K[] temp; // reference used only for swapping 115 | for (int i=1; i < n; i *= 2) { // each iteration sorts all runs of length i 116 | for (int j=0; j < n; j += 2*i) // each pass merges two runs of length i 117 | merge(src, dest, comp, j, i); 118 | temp = src; src = dest; dest = temp; // reverse roles of the arrays 119 | } 120 | if (orig != src) 121 | System.arraycopy(src, 0, orig, 0, n); // additional copy to get result to original 122 | } 123 | } 124 | --------------------------------------------------------------------------------