├── .gitignore ├── lib ├── algs4.jar └── stdlib.jar ├── .classpath ├── .project ├── src ├── Subset.java ├── KdTreeVisualizer.java ├── Outcast.java ├── MoveToFront.java ├── PointSET.java ├── Brute.java ├── Percolation.java ├── PercolationStats.java ├── RandomizedQueue.java ├── NearestNeighborVisualizer.java ├── Fast.java ├── Point.java ├── Deque.java ├── BurrowsWheeler.java ├── CircularSuffixArray.java ├── Solver.java ├── RectHV.java ├── RangeSearchVisualizer.java ├── SAP.java ├── WordNet.java ├── Board.java ├── SeamCarver.java ├── KdTreeTest.java ├── BaseballElimination.java └── KdTree.java └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | -------------------------------------------------------------------------------- /lib/algs4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhichaoh/Coursera-Algorithms/HEAD/lib/algs4.jar -------------------------------------------------------------------------------- /lib/stdlib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhichaoh/Coursera-Algorithms/HEAD/lib/stdlib.jar -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Coursera-Algorithms 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Subset.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Collections; 3 | import java.util.List; 4 | 5 | 6 | public class Subset { 7 | public static void main(String[] args) { 8 | int k = Integer.parseInt(args[0]); 9 | List queue = new ArrayList(); 10 | while(!StdIn.isEmpty()) queue.add(StdIn.readString()); 11 | Collections.shuffle(queue); 12 | for(int i=0;i 0; chars[count] = chars[--count]); 34 | chars[count] = ch; // assert count == 0; 35 | BinaryStdOut.write(ch); 36 | } 37 | BinaryStdOut.close(); 38 | } 39 | 40 | private static char[] radixList() { 41 | char[] rl = new char[R]; 42 | for (char i = 0; i < R; rl[i] = i++); 43 | return rl; 44 | } 45 | 46 | // if args[0] is '-', apply move-to-front encoding 47 | // if args[0] is '+', apply move-to-front decoding 48 | public static void main(String[] args) throws IOException { 49 | if (args[0].equals("-")) 50 | encode(); 51 | else if (args[0].equals("+")) 52 | decode(); 53 | else 54 | return; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/PointSET.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | import java.util.Set; 4 | import java.util.TreeSet; 5 | 6 | 7 | public class PointSET { 8 | 9 | private Set pointSet; 10 | 11 | public PointSET() { 12 | // construct an empty set of points 13 | pointSet = new TreeSet(); 14 | } 15 | 16 | public boolean isEmpty() { 17 | // is the set empty? 18 | return pointSet.isEmpty(); 19 | } 20 | 21 | public int size() { 22 | // number of points in the set 23 | return pointSet.size(); 24 | } 25 | 26 | public void insert(Point2D p) { 27 | // add the point p to the set (if it is not already in the set) 28 | pointSet.add(p); 29 | } 30 | 31 | public boolean contains(Point2D p) { 32 | // does the set contain the point p? 33 | return pointSet.contains(p); 34 | } 35 | 36 | public void draw() { 37 | // draw all of the points to standard draw 38 | for(Point2D p : pointSet){ 39 | p.draw(); 40 | } 41 | } 42 | 43 | public Iterable range(RectHV rect) { 44 | // all points in the set that are inside the rectangle 45 | List pointList = new LinkedList(); 46 | for(Point2D p : pointSet){ 47 | if(rect.distanceTo(p)==0D) pointList.add(p); 48 | } 49 | return pointList; 50 | } 51 | 52 | public Point2D nearest(Point2D p) { 53 | // a nearest neighbor in the set to p; null if set is empty 54 | if(pointSet==null || pointSet.size()==0) return null; 55 | Point2D nn = null; 56 | double dist = Double.MAX_VALUE; 57 | for(Point2D cp : pointSet) { 58 | double cd = cp.distanceTo(p); 59 | if(cd readList(String fileName) throws IOException { 12 | Scanner input = new Scanner(new File(fileName)); 13 | int numPoints = input.nextInt(); 14 | List points = new ArrayList(); 15 | for(int i=0;i points = readList(fileName); 28 | Collections.sort(points); 29 | StdDraw.setXscale(0, 32768); 30 | StdDraw.setYscale(0, 32768); 31 | for(int i=0;i "); 42 | System.out.print(points.get(j)+" -> "); 43 | System.out.print(points.get(k)+" -> "); 44 | System.out.print(points.get(l)+"\n"); 45 | points.get(i).drawTo(points.get(l)); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/Percolation.java: -------------------------------------------------------------------------------- 1 | public class Percolation { 2 | 3 | private boolean[] mat = null; 4 | 5 | private int N = 0; 6 | 7 | private WeightedQuickUnionUF qfObj = null; 8 | 9 | private WeightedQuickUnionUF qfObjEx = null; 10 | 11 | private final int[] mx = { -1, 0, 1, 0 }; 12 | 13 | private final int[] my = { 0, -1, 0, 1 }; 14 | 15 | public Percolation(int N) { // create N-by-N grid, with all sites blocked 16 | mat = new boolean[N * N]; 17 | for (int i = 0; i < N; i++) 18 | for (int j = 0; j < N; j++) 19 | mat[i * N + j] = false; 20 | this.N = N; 21 | qfObj = new WeightedQuickUnionUF(N * N + 2); 22 | qfObjEx = new WeightedQuickUnionUF(N * N + 1); 23 | } 24 | 25 | public void open(int i, int j) { // open site (row i, column j) if it is not 26 | // already 27 | if (i < 1 || j < 1 || i > N || j > N) 28 | throw new java.lang.IndexOutOfBoundsException(); 29 | int ni = i - 1, nj = j - 1; 30 | if (!mat[ni * N + nj]) { 31 | mat[ni * N + nj] = true; 32 | for (int m = 0; m < 4; m++) { 33 | int mi = ni + mx[m]; 34 | int mj = nj + my[m]; 35 | if (mi >= 0 && mj >= 0 && mi < N && mj < N && mat[mi * N + mj]) { 36 | qfObj.union(ni * N + nj, mi * N + mj); 37 | qfObjEx.union(ni * N + nj, mi * N + mj); 38 | } 39 | } 40 | if (i == 1) { 41 | qfObj.union(ni * N + nj, N * N); 42 | qfObjEx.union(ni * N + nj, N * N); 43 | } 44 | if (i == N) 45 | qfObj.union(ni * N + nj, N * N + 1); 46 | } 47 | } 48 | 49 | public boolean isOpen(int i, int j) { // is site (row i, column j) open? 50 | if (i < 1 || j < 1 || i > N || j > N) 51 | throw new java.lang.IndexOutOfBoundsException(); 52 | int ni = i - 1, nj = j - 1; 53 | return mat[ni * N + nj]; 54 | } 55 | 56 | public boolean isFull(int i, int j) { // is site (row i, column j) full? 57 | if (i < 1 || j < 1 || i > N || j > N) 58 | throw new java.lang.IndexOutOfBoundsException(); 59 | int ni = i - 1, nj = j - 1; 60 | return mat[ni * N + nj] && qfObjEx.connected(ni * N + nj, N * N); 61 | } 62 | 63 | public boolean percolates() { // does the system percolate? 64 | return qfObj.connected(N * N, N * N + 1); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Coursera: Algorithms 2 | =================== 3 | 4 | Programming Assignments (Algorithms, Part I and II by Kevin Wayne, Robert Sedgewick) 5 | 6 | Part I 7 | 8 | PA-1 Percolation (Union-find) 9 | ### 10 | Specification: 11 | http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 12 | Code: 13 | Percolation.java; 14 | PercolationStats.java 15 | 16 | PA-2 Randomized Queues and Deques (Queue and Stack) 17 | ### 18 | Specification: 19 | http://coursera.cs.princeton.edu/algs4/assignments/queues.html 20 | Code: 21 | Deque.java; 22 | RandomizedQueue.java; 23 | Subset.java 24 | 25 | PA-3 Pattern Recognition (Sort) 26 | ### 27 | Specification: 28 | http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 29 | Code: 30 | Point.java; 31 | Brute.java; 32 | Fast.java 33 | 34 | PA-4 8 Puzzle (Priority Queues) 35 | ### 36 | Specification: 37 | http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 38 | Code: 39 | Point.java; 40 | Board.java; 41 | Solver.java 42 | 43 | PA-5 Kd-Tree (Balanced Search Trees) 44 | ### 45 | Specification: 46 | http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 47 | Code: 48 | PointSET.java; 49 | KdTree.java 50 | 51 | Part II 52 | 53 | PA-1 WordNet 54 | ### 55 | Specification: 56 | http://coursera.cs.princeton.edu/algs4/assignments/wordnet.html 57 | Code: 58 | WordNet.java; 59 | SAP.java; 60 | Outcast.java 61 | 62 | PA-2 Seam Carving 63 | ### 64 | Specification: 65 | http://coursera.cs.princeton.edu/algs4/assignments/seamCarving.html 66 | Code: 67 | SeamCarver.java 68 | 69 | PA-3 Baseball Elimination (Network Flow) 70 | ### 71 | Specification: 72 | http://coursera.cs.princeton.edu/algs4/assignments/baseball.html 73 | Code: 74 | BaseballElimination.java 75 | 76 | PA-4 Burrows-Wheeler Data Compression Algorithm 77 | ### 78 | Specification: 79 | http://coursera.cs.princeton.edu/algs4/assignments/burrows.html 80 | Code: 81 | MoveToFront.java; 82 | BurrowsWheeler.java; 83 | CircularSuffixArray.java -------------------------------------------------------------------------------- /src/PercolationStats.java: -------------------------------------------------------------------------------- 1 | public class PercolationStats { 2 | 3 | private double mean = 0.0; 4 | 5 | private double std = 0.0; 6 | 7 | private double upperConf = 0.0; 8 | 9 | private double lowerConf = 0.0; 10 | 11 | public PercolationStats(int N, int T) { // perform T independent 12 | // computational experiments on an 13 | // N-by-N grid 14 | if (N <= 0 || T <= 0) 15 | throw new java.lang.IllegalArgumentException(); 16 | double[] res = new double[T]; 17 | for (int t = 0; t < T; t++) { 18 | Percolation perObj = new Percolation(N); 19 | for (int c = 0; c < N * N; c++) { 20 | int pt = (int) (Math.random() * N * N); 21 | int i = pt / N + 1, j = pt % N + 1; 22 | while (perObj.isOpen(i, j)) { 23 | pt = (int) (Math.random() * N * N); 24 | i = pt / N + 1; 25 | j = pt % N + 1; 26 | } 27 | perObj.open(i, j); 28 | if (perObj.percolates()) { 29 | res[t] = ((double) c) / (N * N); 30 | break; 31 | } 32 | } 33 | } 34 | // Mean 35 | for (int t = 0; t < T; t++) 36 | mean += res[t]; 37 | mean /= T; 38 | // Std 39 | for (int t = 0; t < T; t++) 40 | std += (res[t] - mean) * (res[t] - mean); 41 | std /= (T - 1); 42 | std = Math.sqrt(std); 43 | // confidence 44 | lowerConf = mean - 1.96 * std / Math.sqrt(T + 0.0); 45 | upperConf = mean + 1.96 * std / Math.sqrt(T + 0.0); 46 | } 47 | 48 | public double mean() { // sample mean of percolation threshold 49 | return mean; 50 | } 51 | 52 | public double stddev() { // sample standard deviation of percolation 53 | // threshold 54 | return std; 55 | } 56 | 57 | public double confidenceLo() { // returns lower bound of the 95% confidence 58 | // interval 59 | return lowerConf; 60 | } 61 | 62 | public double confidenceHi() { // returns upper bound of the 95% confidence 63 | // interval 64 | return upperConf; 65 | } 66 | 67 | public static void main(String[] args) { // test client, described below 68 | PercolationStats ps = new PercolationStats(Integer.parseInt(args[0]), 69 | Integer.parseInt(args[1])); 70 | System.out.println("mean = " + ps.mean()); 71 | System.out.println("stddev = " + ps.stddev()); 72 | System.out.println("95% confidence interval = " + ps.confidenceLo() 73 | + ", " + ps.confidenceHi()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/RandomizedQueue.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Collections; 3 | import java.util.Iterator; 4 | import java.util.List; 5 | 6 | 7 | public class RandomizedQueue implements Iterable { 8 | 9 | private List queue; 10 | 11 | private int count = 0; 12 | 13 | public RandomizedQueue() { // construct an empty randomized queue 14 | queue = new ArrayList(); 15 | count = 0; 16 | } 17 | 18 | public boolean isEmpty() { // is the queue empty? 19 | return count == 0; 20 | } 21 | 22 | public int size() { // return the number of items on the queue 23 | return count; 24 | } 25 | 26 | public void enqueue(Item item) { // add the item 27 | if(item==null) throw new java.lang.NullPointerException(); 28 | queue.add(item); 29 | queue.set(count, item); 30 | count ++; 31 | } 32 | 33 | public Item dequeue() { // delete and return a random item 34 | if(isEmpty()) throw new java.util.NoSuchElementException(); 35 | int pt = (int)(Math.random()*count); 36 | Item current = queue.get(pt); 37 | queue.set(pt, queue.get(count-1)); 38 | count--; 39 | queue.remove(count); 40 | return current; 41 | } 42 | 43 | public Item sample() { // return (but do not delete) a random item 44 | if(isEmpty()) throw new java.util.NoSuchElementException(); 45 | int pt = (int)(Math.random()*count); 46 | return queue.get(pt); 47 | } 48 | 49 | public Iterator iterator() { // return an independent iterator over items in random order 50 | return new RandomizedQueueIterator(); 51 | } 52 | 53 | private class RandomizedQueueIterator implements Iterator { 54 | 55 | List rQ = null; 56 | 57 | int pt; 58 | 59 | public RandomizedQueueIterator(){ 60 | rQ = new ArrayList(); 61 | for(int i=0;i readList(String fileName) throws IOException { 14 | Scanner input = new Scanner(new File(fileName)); 15 | int numPoints = input.nextInt(); 16 | List points = new ArrayList(); 17 | for(int i=0;i points = readList(fileName); 30 | Collections.sort(points); 31 | StdDraw.setXscale(0, 32768); 32 | StdDraw.setYscale(0, 32768); 33 | for(int i=0;i printedMap = new HashMap(); 35 | for(int i=0;i tmpPoints = new ArrayList(); 37 | for(int j=i+1;j nList = new ArrayList(); 42 | nList.add(points.get(i)); nList.add(tmpPoints.get(j)); 43 | j++; 44 | while(j=4) { 49 | boolean printedFlag = false; 50 | for(int k=0;k "); 60 | System.out.print(nList.get(nList.size()-1)+"\n"); 61 | points.get(i).drawTo(nList.get(nList.size()-1)); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/Point.java: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Name: 3 | * Email: 4 | * 5 | * Compilation: javac Point.java 6 | * Execution: 7 | * Dependencies: StdDraw.java 8 | * 9 | * Description: An immutable data type for points in the plane. 10 | * 11 | *************************************************************************/ 12 | 13 | import java.util.Comparator; 14 | 15 | public class Point implements Comparable { 16 | 17 | // compare points by slope 18 | public final Comparator SLOPE_ORDER = new SlopeOrder(); // YOUR DEFINITION HERE 19 | 20 | private class SlopeOrder implements Comparator { 21 | public int compare(Point a, Point b) { 22 | double slopeA = slopeTo(a); 23 | double slopeB = slopeTo(b); 24 | if(slopeA>slopeB) return 1; 25 | else if(slopeAthat.y) return 1; 65 | else if(this.y==that.y) { 66 | if(this.x>that.x) return 1; 67 | else if(this.x==that.x) return 0; 68 | else return -1; 69 | } 70 | return -1; 71 | } 72 | 73 | // return string representation of this point 74 | public String toString() { 75 | /* DO NOT MODIFY */ 76 | return "(" + x + ", " + y + ")"; 77 | } 78 | 79 | // unit test 80 | public static void main(String[] args) { 81 | 82 | } 83 | } -------------------------------------------------------------------------------- /src/Deque.java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | 3 | public class Deque implements Iterable { 4 | 5 | private class Node { 6 | public Item value = null; 7 | public Node next = null; 8 | public Node prev = null; 9 | } 10 | 11 | private int size; 12 | 13 | private Node head; 14 | 15 | private Node tail; 16 | 17 | public Deque() { // construct an empty deque 18 | size = 0; 19 | head = tail = null; 20 | } 21 | 22 | public boolean isEmpty() { // is the deque empty? 23 | return size == 0; 24 | } 25 | 26 | public int size() { // return the number of items on the deque 27 | return size; 28 | } 29 | 30 | public void addFirst(Item item) { // insert the item at the front 31 | if(item==null) throw new java.lang.NullPointerException(); 32 | Node currentNode = new Node(); 33 | currentNode.value = item; 34 | currentNode.next = head; 35 | if(head!=null) head.prev = currentNode; 36 | head = currentNode; 37 | size ++; 38 | if(tail==null) tail = head; 39 | } 40 | 41 | public void addLast(Item item) { // insert the item at the end 42 | if(item==null) throw new java.lang.NullPointerException(); 43 | Node currentNode = new Node(); 44 | currentNode.value = item; 45 | currentNode.prev = tail; 46 | if(tail!=null) tail.next = currentNode; 47 | tail = currentNode; 48 | size ++; 49 | if(head==null) head = tail; 50 | } 51 | 52 | public Item removeFirst() { // delete and return the item at the front 53 | if(size==0) throw new java.util.NoSuchElementException(); 54 | Item result = head.value; 55 | if(size==1) head = tail = null; 56 | else { 57 | head = head.next; 58 | head.prev = null; 59 | } 60 | size --; 61 | return result; 62 | } 63 | 64 | public Item removeLast() { // delete and return the item at the end 65 | if(size==0) throw new java.util.NoSuchElementException(); 66 | Item result = tail.value; 67 | if(size==1) head = tail = null; 68 | else { 69 | tail = tail.prev; 70 | tail.next = null; 71 | } 72 | size --; 73 | return result; 74 | } 75 | 76 | public Iterator iterator() { // return an iterator over items in order from front to end 77 | return new DequeIterator(); 78 | } 79 | 80 | private class DequeIterator implements Iterator { 81 | 82 | private Node currentNode = head; 83 | 84 | @Override 85 | public boolean hasNext() { 86 | return currentNode!=null; 87 | } 88 | 89 | @Override 90 | public Item next() { 91 | if (!hasNext()) throw new java.util.NoSuchElementException(); 92 | Item item = currentNode.value; 93 | currentNode = currentNode.next; 94 | return item; 95 | } 96 | 97 | @Override 98 | public void remove() { 99 | throw new UnsupportedOperationException(); 100 | } 101 | 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/BurrowsWheeler.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Comparator; 3 | 4 | public class BurrowsWheeler { 5 | 6 | private static int[] argsort(final char[] a, final boolean ascending) { 7 | Integer[] indexes = new Integer[a.length]; 8 | for (int i = 0; i < indexes.length; i++) { 9 | indexes[i] = i; 10 | } 11 | Arrays.sort(indexes, new Comparator() { 12 | @Override 13 | public int compare(final Integer i1, final Integer i2) { 14 | return (ascending ? 1 : -1) * Float.compare(a[i1], a[i2]); 15 | } 16 | }); 17 | return asArray(indexes); 18 | } 19 | 20 | @SafeVarargs 21 | private static int[] asArray(final T... a) { 22 | int[] b = new int[a.length]; 23 | for (int i = 0; i < b.length; i++) { 24 | b[i] = a[i].intValue(); 25 | } 26 | return b; 27 | } 28 | 29 | // apply Burrows-Wheeler encoding, reading from standard input and writing 30 | // to standard output 31 | public static void encode() { 32 | 33 | StringBuilder str = new StringBuilder(); 34 | while (!BinaryStdIn.isEmpty()) 35 | str = str.append(BinaryStdIn.readChar()); 36 | CircularSuffixArray csa = new CircularSuffixArray(str.toString()); 37 | for (int i = 0; i < csa.length(); i++) { 38 | if (csa.index(i) == 0) { 39 | BinaryStdOut.write(i, 32); 40 | // System.out.printf("%c%c%c%c",0,0,0,i); 41 | break; 42 | } 43 | } 44 | for (int i = 0; i < csa.length(); i++) { 45 | // System.out.print(str.charAt((csa.index(i) - 1 + csa.length()) % 46 | // csa.length())); 47 | BinaryStdOut.write(str.charAt((csa.index(i) - 1 + csa.length()) 48 | % csa.length())); 49 | } 50 | BinaryStdIn.close(); 51 | BinaryStdOut.close(); 52 | } 53 | 54 | // apply Burrows-Wheeler decoding, reading from standard input and writing 55 | // to standard output 56 | public static void decode() { 57 | StringBuilder str = new StringBuilder(); 58 | int s = BinaryStdIn.readInt(32); 59 | while (!BinaryStdIn.isEmpty()) 60 | str = str.append(BinaryStdIn.readChar()); 61 | int next[] = new int[str.length()]; 62 | // System.out.println(s+" "+str.length()); 63 | // build next array 64 | int[] index = argsort(str.toString().toCharArray(), true); 65 | for (int i = 0; i < str.length(); i++) { 66 | next[i] = index[i]; 67 | // System.out.println(next[i]); 68 | } 69 | 70 | // output 71 | int idx = 0; 72 | int pt = next[s]; 73 | while (idx < str.length() - 1) { 74 | BinaryStdOut.write(str.charAt(pt)); 75 | // System.out.print(str.charAt(pt)); 76 | pt = next[pt]; 77 | idx++; 78 | } 79 | BinaryStdOut.write(str.charAt(s)); 80 | // System.out.print(str.charAt(s)); 81 | BinaryStdIn.close(); 82 | BinaryStdOut.close(); 83 | } 84 | 85 | // if args[0] is '-', apply Burrows-Wheeler encoding 86 | // if args[0] is '+', apply Burrows-Wheeler decoding 87 | public static void main(String[] args) { 88 | if (args[0].equals("-")) 89 | encode(); 90 | else if (args[0].equals("+")) 91 | decode(); 92 | else 93 | return; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/CircularSuffixArray.java: -------------------------------------------------------------------------------- 1 | 2 | public class CircularSuffixArray { 3 | 4 | private int[] index = null; 5 | 6 | private static final int CUTOFF = 15; 7 | 8 | public int length() { // length of s 9 | return index.length; 10 | } 11 | 12 | public int index(int i) { // returns index of ith sorted suffix 13 | return index[i]; 14 | } 15 | 16 | // circular suffix array of s 17 | public CircularSuffixArray(String s) { 18 | index = new int[s.length()]; 19 | for (int i = 0; i < s.length(); i++) 20 | index[i] = i; 21 | sort(s, 0, s.length() - 1, 0); 22 | } 23 | 24 | private char charAt(String s, int suffix, int offset) { 25 | return s.charAt((suffix + offset) % s.length()); 26 | } 27 | 28 | // 3-way String Quicksort circular suffixes of string s from lo to hi 29 | // starting at index offset. Code adapted from 30 | // http://algs4.cs.princeton.edu/51radix/Quick3string.java.html 31 | private void sort(String s, int lo, int hi, int offset) { 32 | if (hi - lo <= CUTOFF) { 33 | insertion(s, lo, hi, offset); 34 | return; 35 | } 36 | int lt = lo, gt = hi, piv = charAt(s, index[lo], offset), eq = lo + 1; 37 | while (eq <= gt) { 38 | int t = charAt(s, index[eq], offset); 39 | if (t < piv) exch(lt++, eq++); 40 | else if (t > piv) exch(eq, gt--); 41 | else eq++; 42 | } 43 | sort(s, lo, lt - 1, offset); 44 | if (piv >= 0) 45 | sort(s, lt, gt, offset + 1); 46 | sort(s, gt + 1, hi, offset); 47 | } 48 | 49 | private void exch(int i, int j) { 50 | int tmp = index[i]; 51 | index[i] = index[j]; 52 | index[j] = tmp; 53 | } 54 | 55 | // Insertion sort starting at index offset. Code adapted from 56 | // http://algs4.cs.princeton.edu/51radix/Quick3string.java.html 57 | private void insertion(String s, int lo, int hi, int offset) { 58 | for (int i = lo; i <= hi; i++) 59 | for (int j = i; j > lo && less(s, j, j - 1, offset); j--) 60 | exch(j, j - 1); 61 | } 62 | 63 | // Is suffix i less than suffix j, starting at offset 64 | private boolean less(String s, int i, int j, int offset) { 65 | int oi = index[i], oj = index[j]; 66 | for (; offset < index.length; offset++) { 67 | int ival = charAt(s, oi, offset), jval = charAt(s, oj, offset); 68 | if (ival < jval) 69 | return true; 70 | else if (ival > jval) 71 | return false; 72 | } 73 | return false; 74 | } 75 | 76 | public static void main(String[] args) { 77 | int SCREEN_WIDTH = 80; 78 | String s = BinaryStdIn.readString(); 79 | int n = s.length(); 80 | int digits = (int) Math.log10(n) + 1; 81 | String fmt = "%" + (digits == 0 ? 1 : digits) + "d "; 82 | StdOut.printf("String length: %d\n", n); 83 | CircularSuffixArray csa = new CircularSuffixArray(s); 84 | for (int i = 0; i < n; i++) { 85 | StdOut.printf(fmt, i); 86 | for (int j = 0; j < (SCREEN_WIDTH - digits - 1) && j < n; j++) { 87 | char c = s.charAt((j + csa.index(i)) % n); 88 | if (c == '\n') 89 | c = ' '; 90 | StdOut.print(c); 91 | } 92 | StdOut.println(); 93 | } 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /src/Solver.java: -------------------------------------------------------------------------------- 1 | public class Solver { 2 | 3 | private class Node implements Comparable { 4 | private Board board; 5 | private int numMoves; 6 | private Node previous; 7 | public Node(Board board, Node previous){ 8 | this.board = board; 9 | this.previous = previous; 10 | if(previous==null) this.numMoves = 0; 11 | else this.numMoves = previous.numMoves + 1; 12 | } 13 | @Override 14 | public int compareTo(Node o) { 15 | return (this.board.manhattan() - o.board.manhattan()) + (this.numMoves - o.numMoves); 16 | } 17 | 18 | }; 19 | 20 | private Node lastNode = null; 21 | 22 | public Solver(Board initial) { 23 | // find a solution to the initial board (using the A* algorithm) 24 | MinPQ Q = new MinPQ(); 25 | MinPQ SQ = new MinPQ(); 26 | Q.insert(new Node(initial, null)); 27 | SQ.insert(new Node(initial.twin(), null)); 28 | 29 | boolean sSolvable = false; 30 | boolean solvable = false; 31 | while(!solvable && !sSolvable) { //!solvable && 32 | lastNode = expand(Q); 33 | solvable = (lastNode!=null); 34 | sSolvable = (expand(SQ)!=null); 35 | } 36 | } 37 | 38 | private Node expand(MinPQ queue){ 39 | if(queue.isEmpty()) return null; 40 | Node current = queue.delMin(); 41 | //StdOut.println(current.board); 42 | if(current.board.isGoal()) return current; 43 | 44 | for(Board b : current.board.neighbors()) { 45 | if(current.previous==null || !b.equals(current.previous.board)) { 46 | queue.insert(new Node(b, current)); 47 | } 48 | } 49 | return null; 50 | } 51 | 52 | public boolean isSolvable() { 53 | // is the initial board solvable? 54 | return lastNode!=null; 55 | } 56 | 57 | public int moves() { 58 | // min number of moves to solve initial board; -1 if no solution 59 | if(lastNode!=null) return lastNode.numMoves; 60 | else return -1; 61 | } 62 | 63 | public Iterable solution() { 64 | // sequence of boards in a shortest solution; null if no solution 65 | if(lastNode!=null){ 66 | Stack res = new Stack(); 67 | for(Node tail=lastNode; tail!=null; tail = tail.previous){ 68 | res.push(tail.board); 69 | } 70 | return res; 71 | } 72 | else return null; 73 | } 74 | 75 | public static void main(String[] args) { 76 | // create initial board from file 77 | In in = new In("./8puzzle/puzzle12.txt"); 78 | int N = in.readInt(); 79 | int[][] blocks = new int[N][N]; 80 | for (int i = 0; i < N; i++) 81 | for (int j = 0; j < N; j++) 82 | blocks[i][j] = in.readInt(); 83 | Board initial = new Board(blocks); 84 | 85 | // solve the puzzle 86 | Solver solver = new Solver(initial); 87 | 88 | // print solution to standard output 89 | if (!solver.isSolvable()) 90 | StdOut.println("No solution possible"); 91 | else { 92 | StdOut.println("Minimum number of moves = " + solver.moves()); 93 | for (Board board : solver.solution()) 94 | StdOut.println(board); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/RectHV.java: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Compilation: javac RectHV.java 3 | * Execution: java RectHV 4 | * Dependencies: Point2D.java 5 | * 6 | * Implementation of 2D axis-aligned rectangle. 7 | * 8 | *************************************************************************/ 9 | 10 | public class RectHV { 11 | private final double xmin, ymin; // minimum x- and y-coordinates 12 | private final double xmax, ymax; // maximum x- and y-coordinates 13 | 14 | // construct the axis-aligned rectangle [xmin, xmax] x [ymin, ymax] 15 | public RectHV(double xmin, double ymin, double xmax, double ymax) { 16 | if (xmax < xmin || ymax < ymin) { 17 | throw new IllegalArgumentException("Invalid rectangle"); 18 | } 19 | this.xmin = xmin; 20 | this.ymin = ymin; 21 | this.xmax = xmax; 22 | this.ymax = ymax; 23 | } 24 | 25 | // accessor methods for 4 coordinates 26 | public double xmin() { return xmin; } 27 | public double ymin() { return ymin; } 28 | public double xmax() { return xmax; } 29 | public double ymax() { return ymax; } 30 | 31 | // width and height of rectangle 32 | public double width() { return xmax - xmin; } 33 | public double height() { return ymax - ymin; } 34 | 35 | // does this axis-aligned rectangle intersect that one? 36 | public boolean intersects(RectHV that) { 37 | return this.xmax >= that.xmin && this.ymax >= that.ymin 38 | && that.xmax >= this.xmin && that.ymax >= this.ymin; 39 | } 40 | 41 | // draw this axis-aligned rectangle 42 | public void draw() { 43 | StdDraw.line(xmin, ymin, xmax, ymin); 44 | StdDraw.line(xmax, ymin, xmax, ymax); 45 | StdDraw.line(xmax, ymax, xmin, ymax); 46 | StdDraw.line(xmin, ymax, xmin, ymin); 47 | } 48 | 49 | // distance from p to closest point on this axis-aligned rectangle 50 | public double distanceTo(Point2D p) { 51 | return Math.sqrt(this.distanceSquaredTo(p)); 52 | } 53 | 54 | // distance squared from p to closest point on this axis-aligned rectangle 55 | public double distanceSquaredTo(Point2D p) { 56 | double dx = 0.0, dy = 0.0; 57 | if (p.x() < xmin) dx = p.x() - xmin; 58 | else if (p.x() > xmax) dx = p.x() - xmax; 59 | if (p.y() < ymin) dy = p.y() - ymin; 60 | else if (p.y() > ymax) dy = p.y() - ymax; 61 | return dx*dx + dy*dy; 62 | } 63 | 64 | // does this axis-aligned rectangle contain p? 65 | public boolean contains(Point2D p) { 66 | return (p.x() >= xmin) && (p.x() <= xmax) 67 | && (p.y() >= ymin) && (p.y() <= ymax); 68 | } 69 | 70 | // are the two axis-aligned rectangles equal? 71 | public boolean equals(Object y) { 72 | if (y == this) return true; 73 | if (y == null) return false; 74 | if (y.getClass() != this.getClass()) return false; 75 | RectHV that = (RectHV) y; 76 | if (this.xmin != that.xmin) return false; 77 | if (this.ymin != that.ymin) return false; 78 | if (this.xmax != that.xmax) return false; 79 | if (this.ymax != that.ymax) return false; 80 | return true; 81 | } 82 | 83 | // return a string representation of this axis-aligned rectangle 84 | public String toString() { 85 | return "[" + xmin + ", " + xmax + "] x [" + ymin + ", " + ymax + "]"; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/RangeSearchVisualizer.java: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Compilation: javac RangeSearchVisualizer.java 3 | * Execution: java RangeSearchVisualizer input.txt 4 | * Dependencies: PointSET.java KdTree.java Point2D.java RectHV.java 5 | * StdDraw.java In.java 6 | * 7 | * Read points from a file (specified as a command-line arugment) and 8 | * draw to standard draw. Also draw all of the points in the rectangle 9 | * the user selects by dragging the mouse. 10 | * 11 | * The range search results using the brute-force algorithm are drawn 12 | * in red; the results using the kd-tree algorithms are drawn in blue. 13 | * 14 | *************************************************************************/ 15 | 16 | public class RangeSearchVisualizer { 17 | 18 | public static void main(String[] args) { 19 | 20 | String filename = args[0]; 21 | In in = new In(filename); 22 | 23 | 24 | StdDraw.show(0); 25 | 26 | // initialize the data structures with N points from standard input 27 | PointSET brute = new PointSET(); 28 | KdTree kdtree = new KdTree(); 29 | while (!in.isEmpty()) { 30 | double x = in.readDouble(); 31 | double y = in.readDouble(); 32 | Point2D p = new Point2D(x, y); 33 | kdtree.insert(p); 34 | brute.insert(p); 35 | } 36 | 37 | double x0 = 0.0, y0 = 0.0; // initial endpoint of rectangle 38 | double x1 = 0.0, y1 = 0.0; // current location of mouse 39 | boolean isDragging = false; // is the user dragging a rectangle 40 | 41 | // draw the points 42 | StdDraw.clear(); 43 | StdDraw.setPenColor(StdDraw.BLACK); 44 | StdDraw.setPenRadius(.01); 45 | brute.draw(); 46 | 47 | while (true) { 48 | StdDraw.show(40); 49 | 50 | // user starts to drag a rectangle 51 | if (StdDraw.mousePressed() && !isDragging) { 52 | x0 = StdDraw.mouseX(); 53 | y0 = StdDraw.mouseY(); 54 | isDragging = true; 55 | continue; 56 | } 57 | 58 | // user is dragging a rectangle 59 | else if (StdDraw.mousePressed() && isDragging) { 60 | x1 = StdDraw.mouseX(); 61 | y1 = StdDraw.mouseY(); 62 | continue; 63 | } 64 | 65 | // mouse no longer pressed 66 | else if (!StdDraw.mousePressed() && isDragging) { 67 | isDragging = false; 68 | } 69 | 70 | 71 | RectHV rect = new RectHV(Math.min(x0, x1), Math.min(y0, y1), 72 | Math.max(x0, x1), Math.max(y0, y1)); 73 | // draw the points 74 | StdDraw.clear(); 75 | StdDraw.setPenColor(StdDraw.BLACK); 76 | StdDraw.setPenRadius(.01); 77 | brute.draw(); 78 | 79 | // draw the rectangle 80 | StdDraw.setPenColor(StdDraw.BLACK); 81 | StdDraw.setPenRadius(); 82 | rect.draw(); 83 | 84 | // draw the range search results for brute-force data structure in red 85 | StdDraw.setPenRadius(.03); 86 | StdDraw.setPenColor(StdDraw.RED); 87 | for (Point2D p : brute.range(rect)) 88 | p.draw(); 89 | 90 | // draw the range search results for kd-tree in blue 91 | StdDraw.setPenRadius(.02); 92 | StdDraw.setPenColor(StdDraw.BLUE); 93 | for (Point2D p : kdtree.range(rect)) 94 | p.draw(); 95 | 96 | StdDraw.show(40); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/SAP.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | import java.util.Map.Entry; 4 | 5 | public class SAP { 6 | 7 | private Digraph G; 8 | 9 | // constructor takes a digraph (not necessarily a DAG) 10 | public SAP(Digraph G) { 11 | this.G = new Digraph(G); 12 | } 13 | 14 | private Map getAncestors(int v) { 15 | Queue vQ = new Queue(); 16 | Map vM = new HashMap(); 17 | vQ.enqueue(v); 18 | vM.put(v, 0); 19 | while (!vQ.isEmpty()) { 20 | int head = vQ.dequeue(); 21 | int currentDist = vM.get(head); 22 | for (Integer w : G.adj(head)) { 23 | if (!vM.containsKey(w) || vM.get(w) > currentDist + 1) { 24 | vQ.enqueue(w); 25 | vM.put(w, currentDist + 1); 26 | } 27 | } 28 | } 29 | return vM; 30 | } 31 | 32 | // length of shortest ancestral path between v and w; -1 if no such path 33 | public int length(int v, int w) { 34 | if (v < 0 || v >= G.V()) 35 | throw new IndexOutOfBoundsException(); 36 | if (w < 0 || w >= G.V()) 37 | throw new IndexOutOfBoundsException(); 38 | Map ancestorV = getAncestors(v); 39 | Map ancestorW = getAncestors(w); 40 | int dist = -1; 41 | for (Entry items : ancestorV.entrySet()) { 42 | if (ancestorW.containsKey(items.getKey())) { 43 | int currentDist = ancestorW.get(items.getKey()) 44 | + items.getValue(); 45 | if (dist < 0 || currentDist < dist) 46 | dist = currentDist; 47 | } 48 | } 49 | return dist; 50 | } 51 | 52 | // a common ancestor of v and w that participates in a shortest ancestral 53 | // path; -1 if no such path 54 | public int ancestor(int v, int w) { 55 | Map ancestorV = getAncestors(v); 56 | Map ancestorW = getAncestors(w); 57 | if (v < 0 || v >= G.V()) 58 | throw new IndexOutOfBoundsException(); 59 | if (w < 0 || w >= G.V()) 60 | throw new IndexOutOfBoundsException(); 61 | int dist = -1, anc = -1; 62 | for (Entry items : ancestorV.entrySet()) { 63 | if (ancestorW.containsKey(items.getKey())) { 64 | int currentDist = ancestorW.get(items.getKey()) 65 | + items.getValue(); 66 | if (dist < 0 || currentDist < dist) { 67 | dist = currentDist; 68 | anc = items.getKey(); 69 | } 70 | } 71 | } 72 | return anc; 73 | } 74 | 75 | // length of shortest ancestral path between any vertex in v and any vertex 76 | // in w; -1 if no such path 77 | public int length(Iterable v, Iterable w) 78 | throws IndexOutOfBoundsException { 79 | int dist = -1; 80 | for (Integer eV : v) { 81 | for (Integer eW : w) { 82 | int currentDist = length(eV, eW); 83 | if (currentDist > 0 && (dist < 0 || currentDist < dist)) 84 | dist = currentDist; 85 | } 86 | } 87 | return dist; 88 | } 89 | 90 | // a common ancestor that participates in shortest ancestral path; -1 if no 91 | // such path 92 | public int ancestor(Iterable v, Iterable w) 93 | throws IndexOutOfBoundsException { 94 | int dist = -1, anc = -1; 95 | for (Integer eV : v) { 96 | for (Integer eW : w) { 97 | int currentDist = length(eV, eW); 98 | if (currentDist > 0 && (dist < 0 || currentDist < dist)) { 99 | dist = currentDist; 100 | anc = ancestor(eV, eW); 101 | } 102 | } 103 | } 104 | return anc; 105 | } 106 | 107 | // for unit testing of this class (such as the one below) 108 | public static void main(String[] args) { 109 | In in = new In(args[0]); 110 | Digraph G = new Digraph(in); 111 | SAP sap = new SAP(G); 112 | while (!StdIn.isEmpty()) { 113 | int v = StdIn.readInt(); 114 | int w = StdIn.readInt(); 115 | int length = sap.length(v, w); 116 | int ancestor = sap.ancestor(v, w); 117 | StdOut.printf("length = %d, ancestor = %d\n", length, ancestor); 118 | } 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/WordNet.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.FileReader; 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | import java.util.Iterator; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Stack; 10 | 11 | public class WordNet { 12 | 13 | private Map> dict = new HashMap>(); 14 | 15 | private Map reverseDict = new HashMap(); 16 | 17 | private SAP sapObj; 18 | 19 | private boolean dfs(int v, Digraph G, Map visit, 20 | Stack S) { 21 | visit.put(v, true); 22 | S.push(v); 23 | for (int w : G.adj(v)) { 24 | if (S.contains(w)) 25 | return false; 26 | if (!visit.containsKey(w)) 27 | if (!dfs(w, G, visit, S)) 28 | return false; 29 | } 30 | S.pop(); 31 | return true; 32 | } 33 | 34 | private boolean isDAG(Digraph G) { 35 | Map visit = new HashMap(); 36 | Stack S = new Stack(); 37 | for (int i = 0; i < G.V(); i++) { 38 | if (!visit.containsKey(i)) 39 | if (!dfs(i, G, visit, S)) 40 | return false; 41 | } 42 | // check multiple roots 43 | int cnt = 0; 44 | for (int i = 0; i < G.V(); i++) { 45 | int n = 0; 46 | Iterator it = G.adj(i).iterator(); 47 | while (it.hasNext()) { 48 | n += 1; 49 | it.next(); 50 | } 51 | if (n == 0) 52 | cnt += 1; 53 | } 54 | if (cnt != 1) 55 | return false; 56 | return true; 57 | } 58 | 59 | // constructor takes the name of the two input files 60 | public WordNet(String synsets, String hypernyms) 61 | throws IllegalArgumentException, IOException { 62 | // reading synsets 63 | BufferedReader in = new BufferedReader(new FileReader(synsets)); 64 | String line = null; 65 | int maxID = 0; 66 | while ((line = in.readLine()) != null) { 67 | String items[] = line.split(","); 68 | String nouns[] = items[1].split(" "); 69 | List nounList = null; 70 | for (int i = 0; i < nouns.length; i++) { 71 | if (!dict.containsKey(nouns[i])) 72 | nounList = new LinkedList(); 73 | else 74 | nounList = dict.get(nouns[i]); 75 | nounList.add(Integer.parseInt(items[0])); 76 | dict.put(nouns[i], nounList); 77 | } 78 | reverseDict.put(Integer.parseInt(items[0]), items[1]); 79 | maxID = Math.max(maxID, Integer.parseInt(items[0])); 80 | } 81 | in.close(); 82 | // reading hypernyms 83 | Digraph G = new Digraph(maxID + 1); 84 | in = new BufferedReader(new FileReader(hypernyms)); 85 | while ((line = in.readLine()) != null) { 86 | String items[] = line.split(","); 87 | int v = Integer.parseInt(items[0]); 88 | for (int i = 1; i < items.length; i++) 89 | G.addEdge(v, Integer.parseInt(items[i])); 90 | } 91 | in.close(); 92 | if (!isDAG(G)) 93 | throw new IllegalArgumentException(); 94 | // initializing 95 | sapObj = new SAP(G); 96 | } 97 | 98 | // returns all WordNet nouns 99 | public Iterable nouns() { 100 | return dict.keySet(); 101 | } 102 | 103 | // is the word a WordNet noun? 104 | public boolean isNoun(String word) { 105 | return dict.containsKey(word); 106 | } 107 | 108 | // distance between nounA and nounB (defined below) 109 | public int distance(String nounA, String nounB) { 110 | // System.out.println(nounA+"\t"+nounB); 111 | if (!isNoun(nounA) || !isNoun(nounB)) 112 | throw new IllegalArgumentException(); 113 | return sapObj.length(dict.get(nounA), dict.get(nounB)); 114 | } 115 | 116 | // a synset (second field of synsets.txt) that is the common ancestor of 117 | // nounA and nounB 118 | // in a shortest ancestral path (defined below) 119 | public String sap(String nounA, String nounB) { 120 | if (!isNoun(nounA) || !isNoun(nounB)) 121 | throw new IllegalArgumentException(); 122 | int id = sapObj.ancestor(dict.get(nounA), dict.get(nounB)); 123 | return reverseDict.get(id); 124 | } 125 | 126 | // for unit testing of this class 127 | public static void main(String[] args) throws IllegalArgumentException, 128 | IOException { 129 | WordNet wordnet = new WordNet(args[0], args[1]); 130 | wordnet.distance("wolf", "fish"); 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /src/Board.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.List; 4 | 5 | 6 | 7 | public class Board { 8 | 9 | private int N; 10 | 11 | private int[][] board; 12 | 13 | private int[][] copyBoard(int[][] src) { 14 | int[][] tar = new int[src.length][src.length]; 15 | for(int i=0;i0 && newBoard[i][j+1]>0) { 74 | int tmp = newBoard[i][j]; 75 | newBoard[i][j] = newBoard[i][j+1]; 76 | newBoard[i][j+1] = tmp; 77 | flag = true; 78 | break; 79 | } 80 | } 81 | if(flag) break; 82 | } 83 | return new Board(newBoard); 84 | } 85 | 86 | public boolean equals(Object y) { 87 | // does this board equal y? 88 | if(y==this) return true; 89 | if(y==null) return false; 90 | if(!(y instanceof Board)) return false; 91 | if(((Board)y).N!=this.N) return false; 92 | for (int r = 0; r < N; r++) 93 | if (!Arrays.equals(this.board[r], ((Board)y).board[r])) 94 | return false; 95 | return true; 96 | } 97 | 98 | public Iterable neighbors() { 99 | // all neighboring boards 100 | List boards = new ArrayList(); 101 | int[] mx = {1,-1,0,0}; 102 | int[] my = {0,0,1,-1}; 103 | boolean foundFlag = false; 104 | for(int i=0;i=0 && nj>=0 && ni= pic.width() || y >= pic.height()) 32 | throw new IndexOutOfBoundsException(); 33 | else if (x == 0 || y == 0 || x == pic.width() - 1 34 | || y == pic.height() - 1) 35 | return 195075.0; 36 | else { 37 | Color xp1y = pic.get(x + 1, y); 38 | Color xn1y = pic.get(x - 1, y); 39 | Color xyp1 = pic.get(x, y + 1); 40 | Color xyn1 = pic.get(x, y - 1); 41 | double detX = (xn1y.getRed() - xp1y.getRed()) 42 | * (xn1y.getRed() - xp1y.getRed()) 43 | + (xn1y.getBlue() - xp1y.getBlue()) 44 | * (xn1y.getBlue() - xp1y.getBlue()) 45 | + (xn1y.getGreen() - xp1y.getGreen()) 46 | * (xn1y.getGreen() - xp1y.getGreen()); 47 | double detY = (xyn1.getRed() - xyp1.getRed()) 48 | * (xyn1.getRed() - xyp1.getRed()) 49 | + (xyn1.getBlue() - xyp1.getBlue()) 50 | * (xyn1.getBlue() - xyp1.getBlue()) 51 | + (xyn1.getGreen() - xyp1.getGreen()) 52 | * (xyn1.getGreen() - xyp1.getGreen()); 53 | return detX + detY; 54 | } 55 | } 56 | 57 | private void dfsMinPath(int x, int y, double[][] sumEnergy, 58 | double[][] energy, int[][] steps, boolean horizontal) { 59 | if ((horizontal && x == pic.width() - 1) 60 | || (!horizontal && y == pic.height() - 1)) { 61 | sumEnergy[y][x] = energy[y][x]; 62 | steps[y][x] = -1; 63 | return; 64 | } 65 | double minPath = Double.MAX_VALUE; 66 | int bestMv = 0; 67 | for (int mv = -1; mv <= 1; mv++) { 68 | if (horizontal) { 69 | int py = y + mv; 70 | if (py >= pic.height() || py < 0) 71 | continue; 72 | if (steps[py][x + 1] == 0) 73 | dfsMinPath(x + 1, py, sumEnergy, energy, steps, horizontal); 74 | if (sumEnergy[py][x + 1] < minPath) { 75 | minPath = sumEnergy[py][x + 1]; 76 | bestMv = py; 77 | } 78 | } else { 79 | int px = x + mv; 80 | if (px >= pic.width() || px < 0) 81 | continue; 82 | if (steps[y + 1][px] == 0) 83 | dfsMinPath(px, y + 1, sumEnergy, energy, steps, horizontal); 84 | if (sumEnergy[y + 1][px] < minPath) { 85 | minPath = sumEnergy[y + 1][px]; 86 | bestMv = px; 87 | } 88 | } 89 | } 90 | steps[y][x] = bestMv; 91 | sumEnergy[y][x] = energy[y][x] + minPath; 92 | } 93 | 94 | private void calSumEnergy() { 95 | for (int j = 0; j < pic.height(); j++) 96 | for (int i = 0; i < pic.width(); i++) { 97 | energy[j][i] = this.energy(i, j); 98 | } 99 | } 100 | 101 | public int[] findHorizontalSeam() { 102 | // sequence of indices for horizontal seam 103 | int[][] steps = new int[pic.height()][pic.width()]; 104 | double[][] sumEnergy = new double[pic.height()][pic.width()]; 105 | this.calSumEnergy(); 106 | for (int y = 0; y < this.height(); y++) 107 | this.dfsMinPath(0, y, sumEnergy, energy, steps, true); 108 | int[] ht = new int[pic.width()]; 109 | double bestEnergy = Double.MAX_VALUE; 110 | for (int y = 0; y < this.height(); y++) { 111 | if (sumEnergy[y][0] < bestEnergy) { 112 | bestEnergy = sumEnergy[y][0]; 113 | ht[0] = y; 114 | } 115 | } 116 | for (int x = 1; x < this.width(); x++) { 117 | ht[x] = steps[ht[x - 1]][x - 1]; 118 | } 119 | return ht; 120 | } 121 | 122 | public int[] findVerticalSeam() { 123 | // sequence of indices for vertical seam 124 | int[][] steps = new int[pic.height()][pic.width()]; 125 | double[][] sumEnergy = new double[pic.height()][pic.width()]; 126 | this.calSumEnergy(); 127 | for (int x = 0; x < this.width(); x++) 128 | this.dfsMinPath(x, 0, sumEnergy, energy, steps, false); 129 | int[] ht = new int[pic.height()]; 130 | double bestEnergy = Double.MAX_VALUE; 131 | for (int x = 0; x < this.width(); x++) { 132 | if (sumEnergy[0][x] < bestEnergy) { 133 | bestEnergy = sumEnergy[0][x]; 134 | ht[0] = x; 135 | } 136 | } 137 | for (int y = 1; y < this.height(); y++) 138 | ht[y] = steps[y - 1][ht[y - 1]]; 139 | return ht; 140 | } 141 | 142 | public void removeHorizontalSeam(int[] a) throws IllegalArgumentException { 143 | // remove horizontal seam from picture 144 | if (a.length != pic.width()) 145 | throw new IllegalArgumentException(); 146 | Picture cPic = new Picture(pic.width(), pic.height() - 1); 147 | for (int i = 0; i < pic.width(); i++) { 148 | for (int j = 0; j < pic.height(); j++) { 149 | if (j == a[i]) 150 | continue; 151 | int pt = j; 152 | if (pt > a[i]) 153 | pt--; 154 | cPic.set(i, pt, this.pic.get(i, j)); 155 | } 156 | } 157 | this.pic = cPic; 158 | } 159 | 160 | public void removeVerticalSeam(int[] a) throws IllegalArgumentException { 161 | // remove vertical seam from picture 162 | if (a.length != pic.height()) 163 | throw new IllegalArgumentException(); 164 | Picture cPic = new Picture(pic.width() - 1, pic.height()); 165 | for (int j = 0; j < pic.height(); j++) { 166 | for (int i = 0; i < pic.width(); i++) { 167 | if (i == a[j]) 168 | continue; 169 | int pt = i; 170 | if (pt > a[j]) 171 | pt--; 172 | cPic.set(pt, j, pic.get(i, j)); 173 | } 174 | } 175 | this.pic = cPic; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/KdTreeTest.java: -------------------------------------------------------------------------------- 1 | import static org.junit.Assert.*; 2 | 3 | import org.junit.Test; 4 | 5 | 6 | 7 | import java.util.Iterator; 8 | import java.util.Arrays; 9 | 10 | import org.junit.Before; 11 | import org.junit.After; 12 | 13 | public class KdTreeTest { 14 | private KdTree k; 15 | 16 | @Before 17 | public void set_up() { 18 | k = new KdTree(); 19 | } 20 | 21 | @After 22 | public void tear_down() {} 23 | 24 | private Point2D[] get_points() { 25 | return new Point2D[]{ 26 | new Point2D(0.3, 0.2), 27 | new Point2D(0.2, 0.2), 28 | new Point2D(0.1, 0.1), 29 | new Point2D(0.2, 0.1), 30 | new Point2D(0.3, 0.3) 31 | }; 32 | } 33 | 34 | @Test 35 | public void test_empty() { 36 | assertEquals(0, k.size()); 37 | assertTrue(k.isEmpty()); 38 | } 39 | 40 | @Test 41 | public void test_insert_first() { 42 | k.insert(new Point2D(0.1, 0.1)); 43 | assertEquals(1, k.size()); 44 | assertFalse(k.isEmpty()); 45 | } 46 | 47 | @Test 48 | public void test_insert_distinct() { 49 | Point2D[] points = get_points(); 50 | for (Point2D point : points) k.insert(point); 51 | assertEquals(points.length, k.size()); 52 | } 53 | 54 | @Test 55 | public void test_insert_same() { 56 | for (int i = 0; i < 5; i++) k.insert(new Point2D(0.1, 0.1)); 57 | assertEquals(1, k.size()); 58 | } 59 | 60 | @Test 61 | public void test_empty_contains() { 62 | assertFalse(k.contains(new Point2D(0.1, 0.1))); 63 | } 64 | 65 | @Test 66 | public void test_single_contains() { 67 | k.insert(new Point2D(0.1, 0.1)); 68 | assertEquals(1, k.size()); 69 | assertTrue(k.contains(new Point2D(0.1, 0.1))); 70 | } 71 | 72 | @Test 73 | public void test_multiple_contains() { 74 | Point2D[] points = get_points(); 75 | for (Point2D point : points) { 76 | k.insert(point); 77 | } 78 | 79 | for (Point2D point : points) { 80 | assertTrue(k.contains(point)); 81 | } 82 | } 83 | 84 | @Test 85 | public void test_not_empty_not_contains() { 86 | Point2D[] points = get_points(); 87 | for (Point2D point : points) k.insert(point); 88 | 89 | assertFalse(k.contains(new Point2D(0.4, 0.4))); 90 | assertFalse(k.contains(new Point2D(0.0, 0.0))); 91 | } 92 | 93 | @Test 94 | public void test_empty_range() { 95 | Iterator iter = k.range(new RectHV(0, 0, 1, 1)).iterator(); 96 | assertFalse(iter.hasNext()); 97 | } 98 | 99 | @Test 100 | public void test_single_range() { 101 | Point2D p = new Point2D(1, 1); 102 | k.insert(p); 103 | 104 | Iterator iter = k.range(new RectHV(0, 0, 1, 1)).iterator(); 105 | assertTrue(iter.hasNext()); 106 | assertTrue(p.equals(iter.next())); 107 | assertFalse(iter.hasNext()); 108 | } 109 | 110 | @Test 111 | public void test_multiple_range() { 112 | Point2D[] points = get_points(); 113 | for (Point2D point : points) k.insert(point); 114 | 115 | Iterator iter = k.range(new RectHV(0, 0, 1, 1)).iterator(); 116 | 117 | int cnt = 0; 118 | while (iter.hasNext()) { 119 | cnt++; 120 | Point2D p = iter.next(); 121 | Arrays.asList(points).contains(p); 122 | } 123 | assertFalse(iter.hasNext()); 124 | assertEquals(points.length, cnt); 125 | } 126 | 127 | @Test 128 | public void test_selected_range() { 129 | Point2D[] points = new Point2D[]{ 130 | new Point2D(.5, .5), 131 | new Point2D(.7, .8), 132 | new Point2D(.1, .1), 133 | new Point2D(1, 0), 134 | new Point2D(.3, .9), 135 | }; 136 | for (Point2D point : points) k.insert(point); 137 | assertEquals(5, k.size()); 138 | 139 | Iterator iter = k.range(new RectHV(.6, .6, .8, .8)).iterator(); 140 | assertTrue(iter.hasNext()); 141 | iter.next().equals(points[1]); 142 | assertFalse(iter.hasNext()); 143 | 144 | iter = k.range(new RectHV(0, 0, .6, .6)).iterator(); 145 | assertTrue(iter.hasNext()); 146 | iter.next().equals(points[2]); 147 | assertTrue(iter.hasNext()); 148 | iter.next().equals(points[0]); 149 | assertFalse(iter.hasNext()); 150 | } 151 | 152 | @Test 153 | public void test_not_empty_no_range() { 154 | Point2D[] points = get_points(); 155 | for (Point2D point : points) k.insert(point); 156 | 157 | Iterator iter = k.range(new RectHV(.4, .4, 1, 1)).iterator(); 158 | assertFalse(iter.hasNext()); 159 | } 160 | 161 | @Test 162 | public void test_empty_nearest() { 163 | assertNull(k.nearest(new Point2D(0, 0))); 164 | } 165 | 166 | @Test 167 | public void test_nearest_single() { 168 | Point2D p = new Point2D(0, 0); 169 | k.insert(p); 170 | assertTrue(p.equals(k.nearest(new Point2D(1, 1)))); 171 | assertTrue(p.equals(k.nearest(p))); 172 | } 173 | 174 | @Test 175 | public void test_nearest_multiple_exact() { 176 | Point2D[] points = get_points(); 177 | for (Point2D point : points) { 178 | k.insert(point); 179 | } 180 | 181 | for (Point2D point : points) { 182 | System.out.println(k.nearest(point)); 183 | System.out.println(point); 184 | assertTrue(point.equals(k.nearest(point))); 185 | } 186 | } 187 | 188 | @Test 189 | public void test_nearest_multiple() { 190 | Point2D[] points = new Point2D[]{ 191 | new Point2D(.5, .5), 192 | new Point2D(.7, .8), 193 | new Point2D(.1, .1), 194 | new Point2D(1, 0), 195 | new Point2D(.3, .9), 196 | }; 197 | for (Point2D point : points) k.insert(point); 198 | 199 | 200 | assertTrue(points[0].equals(k.nearest(new Point2D(.6, .6)))); 201 | assertTrue(points[3].equals(k.nearest(new Point2D(.6, 0)))); 202 | assertTrue(points[4].equals(k.nearest(new Point2D(0, 1)))); 203 | assertTrue(points[2].equals(k.nearest(new Point2D(.2, .2)))); 204 | assertTrue(points[1].equals(k.nearest(new Point2D(1, 1)))); 205 | } 206 | } -------------------------------------------------------------------------------- /src/BaseballElimination.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.util.ArrayList; 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Scanner; 7 | 8 | public class BaseballElimination { 9 | 10 | private int[] w; 11 | 12 | private int[] l; 13 | 14 | private int[] r; 15 | 16 | private int[][] g; 17 | 18 | private Map teamNames; 19 | 20 | private String[] nameList; 21 | 22 | private int numTeams; 23 | 24 | public BaseballElimination(String filename) throws Exception { 25 | // create a baseball division from given filename in format specified 26 | // below 27 | Scanner input = new Scanner(new File(filename)); 28 | numTeams = input.nextInt(); 29 | this.w = new int[numTeams]; 30 | this.l = new int[numTeams]; 31 | this.r = new int[numTeams]; 32 | this.g = new int[numTeams][numTeams]; 33 | this.nameList = new String[numTeams]; 34 | this.teamNames = new HashMap(); 35 | for (int n = 0; n < numTeams; n++) { 36 | String name = input.next(); 37 | teamNames.put(name, n); 38 | w[n] = input.nextInt(); 39 | l[n] = input.nextInt(); 40 | r[n] = input.nextInt(); 41 | for (int m = 0; m < numTeams; m++) 42 | g[n][m] = input.nextInt(); 43 | nameList[n] = name; 44 | } 45 | input.close(); 46 | } 47 | 48 | public int numberOfTeams() { 49 | return this.numTeams; 50 | } 51 | 52 | public Iterable teams() { 53 | // all teams 54 | return teamNames.keySet(); 55 | } 56 | 57 | public int wins(String team) { 58 | // number of wins for given team 59 | if (!teamNames.containsKey(team)) 60 | throw new java.lang.IllegalArgumentException(); 61 | return w[teamNames.get(team)]; 62 | } 63 | 64 | public int losses(String team) { 65 | // number of losses for given team 66 | if (!teamNames.containsKey(team)) 67 | throw new java.lang.IllegalArgumentException(); 68 | return l[teamNames.get(team)]; 69 | } 70 | 71 | public int remaining(String team) { 72 | // number of remaining games for given team 73 | if (!teamNames.containsKey(team)) 74 | throw new java.lang.IllegalArgumentException(); 75 | return r[teamNames.get(team)]; 76 | } 77 | 78 | public int against(String team1, String team2) { 79 | // number of remaining games between team1 and team2 80 | if (!teamNames.containsKey(team1) || !teamNames.containsKey(team2)) 81 | throw new java.lang.IllegalArgumentException(); 82 | int a = teamNames.get(team1); 83 | int b = teamNames.get(team2); 84 | return g[a][b]; 85 | } 86 | 87 | public boolean isEliminated(String team) { 88 | // is given team eliminated? 89 | if (!teamNames.containsKey(team)) 90 | throw new java.lang.IllegalArgumentException(); 91 | int x = teamNames.get(team); 92 | 93 | for (int i = 0; i < this.numTeams; i++) { 94 | if (w[x] + r[x] - w[i] < 0) 95 | return true; 96 | } 97 | 98 | int numMatches = this.numTeams * (this.numTeams - 1) / 2; 99 | int nodeID = 0; 100 | 101 | FlowNetwork fn = new FlowNetwork(numMatches + numTeams + 2); 102 | int s = numMatches + numTeams; 103 | int t = s + 1; 104 | 105 | for (int i = 0; i < numTeams; i++) { 106 | for (int j = i + 1; j < numTeams; j++) { 107 | if (i == j) 108 | continue; 109 | fn.addEdge(new FlowEdge(s, nodeID, g[i][j])); // source to match 110 | // nodes 111 | fn.addEdge(new FlowEdge(nodeID, numMatches + i, 112 | Integer.MAX_VALUE)); // match to team nodes 113 | fn.addEdge(new FlowEdge(nodeID, numMatches + j, 114 | Integer.MAX_VALUE)); // match to team nodes 115 | nodeID += 1; 116 | } 117 | fn.addEdge(new FlowEdge(numMatches + i, t, Math.max(0, w[x] + r[x] 118 | - w[i]))); // game nodes to target 119 | } 120 | 121 | new FordFulkerson(fn, s, t); 122 | 123 | for (FlowEdge e : fn.adj(s)) { 124 | if (e.flow() != e.capacity()) 125 | return true; 126 | } 127 | return false; 128 | } 129 | 130 | public Iterable certificateOfElimination(String team) { 131 | // subset R of teams that eliminates given team; null if not eliminated 132 | if (!teamNames.containsKey(team)) 133 | throw new java.lang.IllegalArgumentException(); 134 | int x = teamNames.get(team); 135 | int numMatches = this.numTeams * (this.numTeams - 1) / 2; 136 | int nodeID = 0; 137 | 138 | List nList = new ArrayList(); 139 | for (int i = 0; i < this.numTeams; i++) { 140 | if (w[x] + r[x] - w[i] < 0) 141 | nList.add(nameList[i]); 142 | } 143 | if (nList.size() > 0) 144 | return nList; 145 | 146 | FlowNetwork fn = new FlowNetwork(numMatches + numTeams + 2); 147 | int s = numMatches + numTeams; 148 | int t = s + 1; 149 | 150 | for (int i = 0; i < numTeams; i++) { 151 | for (int j = i + 1; j < numTeams; j++) { 152 | if (i == j) 153 | continue; 154 | fn.addEdge(new FlowEdge(s, nodeID, g[i][j])); // source to match 155 | // nodes 156 | fn.addEdge(new FlowEdge(nodeID, numMatches + i, 157 | Integer.MAX_VALUE)); // match to team nodes 158 | fn.addEdge(new FlowEdge(nodeID, numMatches + j, 159 | Integer.MAX_VALUE)); // match to team nodes 160 | nodeID += 1; 161 | } 162 | fn.addEdge(new FlowEdge(numMatches + i, t, Math.max(0, w[x] + r[x] 163 | - w[i]))); // game nodes to target 164 | } 165 | 166 | FordFulkerson FF = new FordFulkerson(fn, s, t); 167 | 168 | boolean flag = false; 169 | for (FlowEdge e : fn.adj(s)) { 170 | if (e.flow() != e.capacity()) { 171 | flag = true; 172 | break; 173 | } 174 | } 175 | if (!flag) 176 | return null; 177 | else { 178 | List nodeList = this.BFSRes(fn, s); 179 | List nl = new ArrayList(); 180 | for (Integer v : nodeList) { 181 | if (FF.inCut(v) && v >= numMatches) { 182 | nl.add(this.nameList[v - numMatches]); 183 | } 184 | } 185 | return nl; 186 | } 187 | } 188 | 189 | private List BFSRes(FlowNetwork graph, int node) { 190 | Queue Q = new Queue(); 191 | boolean[] visited = new boolean[graph.V()]; 192 | Q.enqueue(node); 193 | visited[node] = true; 194 | List nodeList = new ArrayList(); 195 | while (!Q.isEmpty()) { 196 | int cn = Q.dequeue(); 197 | for (FlowEdge e : graph.adj(cn)) { 198 | int t = -1; 199 | if (e.from() == cn) 200 | t = e.to(); 201 | else 202 | t = e.from(); 203 | if (e.residualCapacityTo(t) > 0) { 204 | if (!visited[t]) { 205 | Q.enqueue(t); 206 | visited[t] = true; 207 | nodeList.add(t); 208 | } 209 | } 210 | } 211 | } 212 | return nodeList; 213 | } 214 | 215 | public static void main(String[] args) throws Exception { 216 | BaseballElimination division = new BaseballElimination(args[0]); 217 | for (String team : division.teams()) { 218 | if (division.isEliminated(team)) { 219 | StdOut.print(team + " is eliminated by the subset R = { "); 220 | for (String t : division.certificateOfElimination(team)) 221 | StdOut.print(t + " "); 222 | StdOut.println("}"); 223 | } else { 224 | StdOut.println(team + " is not eliminated"); 225 | } 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/KdTree.java: -------------------------------------------------------------------------------- 1 | import java.util.Set; 2 | import java.util.TreeSet; 3 | 4 | 5 | public class KdTree { 6 | 7 | private Node root; 8 | 9 | private int numNodes; 10 | 11 | private class Node implements Comparable { 12 | private Point2D point; 13 | private Node left, right; 14 | private RectHV rect; 15 | private boolean flag; 16 | public Node(Point2D point, boolean flag, RectHV rect){ 17 | this.point = new Point2D(point.x(), point.y()); 18 | this.flag = flag; 19 | this.left = null; 20 | this.right = null; 21 | this.rect = rect; 22 | } 23 | 24 | @Override 25 | public int compareTo(Node o) { 26 | if(flag) { 27 | if(this.point.x()>o.point.x()) return 1; 28 | else if(Math.abs(this.point.x()-o.point.x())<1e-20) return 0; 29 | else return -1; 30 | } else { 31 | if(this.point.y()>o.point.y()) return 1; 32 | else if(Math.abs(this.point.y()-o.point.y())<1e-20) return 0; 33 | else return -1; 34 | } 35 | } 36 | }; 37 | 38 | private Point2D searchRec(Node root, Node p) { 39 | if(root.point.equals(p.point)) return root.point; 40 | if(root.compareTo(p)>0) { 41 | if(root.left==null) return null; 42 | else return searchRec(root.left, p); 43 | } else { 44 | if(root.right==null) return null; 45 | else return searchRec(root.right, p); 46 | } 47 | 48 | } 49 | 50 | private boolean insertRec(Node root, Point2D p){ 51 | if(root.point.equals(p)) return false; 52 | Node newNode = new Node(p, !root.flag, null); 53 | if(root.compareTo(newNode)>0){ 54 | RectHV newRect = null; 55 | if(root.flag) newRect = new RectHV(root.rect.xmin(), root.rect.ymin(), root.point.x(), root.rect.ymax()); 56 | else newRect = new RectHV(root.rect.xmin(), root.rect.ymin(), root.rect.xmax(), root.point.y()); 57 | if(root.left!=null) return insertRec(root.left, p); 58 | else root.left = new Node(p, !root.flag, newRect); 59 | return true; 60 | } else { 61 | RectHV newRect = null; 62 | if(root.flag) newRect = new RectHV(root.point.x(), root.rect.ymin(), root.rect.xmax(), root.rect.ymax()); 63 | else newRect = new RectHV(root.rect.xmin(), root.point.y(), root.rect.xmax(), root.rect.ymax()); 64 | if(root.right!=null) return insertRec(root.right, p); 65 | else root.right = new Node(p, !root.flag, newRect); 66 | return true; 67 | } 68 | } 69 | 70 | private void drawRec(Node root, double minX, double maxX, double minY, double maxY) { 71 | if (root == null) return; 72 | 73 | StdDraw.setPenRadius(.001); 74 | if (root.flag) { 75 | StdDraw.setPenColor(StdDraw.RED); 76 | StdDraw.line(root.point.x(), minY, root.point.x(), maxY); 77 | drawRec(root.left, minX, root.point.x(), minY, maxY); 78 | drawRec(root.right, root.point.x(), maxX, minY, maxY); 79 | } else { 80 | StdDraw.setPenColor(StdDraw.BLUE); 81 | StdDraw.line(minX, root.point.y(), maxX, root.point.y()); 82 | drawRec(root.left, minX, maxX, minY, root.point.y()); 83 | drawRec(root.right, minX, maxX, root.point.y(), maxY); 84 | } 85 | StdDraw.setPenColor(StdDraw.BLACK); 86 | StdDraw.setPenRadius(.01); 87 | root.point.draw(); 88 | } 89 | 90 | private void rangeRec(Node root, RectHV rect, Set set) { 91 | if (root == null) return; 92 | if (root.rect.intersects(rect)) { 93 | if (rect.contains(root.point)) set.add(root.point); 94 | rangeRec(root.left, rect, set); 95 | rangeRec(root.right, rect, set); 96 | } 97 | } 98 | 99 | /* private Node nearestRec(Point2D point, Node root, double dist) { 100 | if (root.rect.distanceSquaredTo(point) >= dist) return root; 101 | Node min = root; 102 | dist = root.point.distanceSquaredTo(point); 103 | 104 | if (root.left != null && root.left.rect.distanceSquaredTo(point) < dist) { 105 | Node left_min = nearestRec(point, root.left, dist); 106 | double left_dist = point.distanceSquaredTo(left_min.point); 107 | if(left_dist rect.distanceSquaredTo(queryPoint)) { 129 | 130 | Point2D nodePoint = new Point2D(node.point.x(), node.point.y()); 131 | 132 | if (nearestPoint == null) { 133 | nearestPoint = nodePoint; 134 | } else { 135 | if (queryPoint.distanceSquaredTo(nearestPoint) > queryPoint.distanceSquaredTo(nodePoint)) { 136 | nearestPoint = nodePoint; 137 | } 138 | } 139 | 140 | if (node.flag) { 141 | if (x <= node.point.x()) { 142 | if(node.left!=null) nearestPoint = nearestHelper(node.left, node.left.rect, x, y, nearestPoint); 143 | if(node.right!=null) nearestPoint = nearestHelper(node.right, node.right.rect, x, y, nearestPoint); 144 | } else { 145 | if(node.right!=null) nearestPoint = nearestHelper(node.right, node.right.rect, x, y, nearestPoint); 146 | if(node.left!=null) nearestPoint = nearestHelper(node.left, node.left.rect, x, y, nearestPoint); 147 | } 148 | } else { 149 | if (y <= node.point.y()) { 150 | if(node.left!=null) nearestPoint = nearestHelper(node.left, node.left.rect, x, y, nearestPoint); 151 | if(node.right!=null) nearestPoint = nearestHelper(node.right, node.right.rect, x, y, nearestPoint); 152 | } else { 153 | if(node.right!=null) nearestPoint = nearestHelper(node.right, node.right.rect, x, y, nearestPoint); 154 | if(node.left!=null) nearestPoint = nearestHelper(node.left, node.left.rect, x, y, nearestPoint); 155 | } 156 | } 157 | } 158 | } 159 | return nearestPoint; 160 | } 161 | 162 | public Point2D nearest(Point2D p) { 163 | return nearestHelper(root, new RectHV(0,0,1,1), p.x(), p.y(), null); 164 | } 165 | 166 | public KdTree() { 167 | // construct an empty set of points 168 | this.root = null; 169 | this.numNodes = 0; 170 | } 171 | 172 | public boolean isEmpty() { 173 | // is the set empty? 174 | return numNodes==0; 175 | } 176 | 177 | public int size() { 178 | // number of points in the set 179 | return this.numNodes; 180 | } 181 | 182 | public void insert(Point2D p) { 183 | // add the point p to the set (if it is not already in the set) 184 | if(this.numNodes==0) { 185 | this.root = new Node(p,true,new RectHV(0,0,1,1)); 186 | this.numNodes ++; 187 | } 188 | else { 189 | if(insertRec(root, p)) this.numNodes++; 190 | } 191 | 192 | } 193 | 194 | public boolean contains(Point2D p) { 195 | // does the set contain the point p? 196 | if(isEmpty()) return false; 197 | return searchRec(root, new Node(p, true, null))!=null; 198 | } 199 | 200 | public void draw() { 201 | // draw all of the points to standard draw 202 | if (isEmpty()) return; 203 | drawRec(root, 0, 1, 0, 1); 204 | } 205 | 206 | public Iterable range(RectHV rect) { 207 | // all points in the set that are inside the rectangle 208 | Set pointList = new TreeSet(); 209 | rangeRec(root, rect, pointList); 210 | return pointList; 211 | } 212 | 213 | /* public Point2D nearest(Point2D p) { 214 | // a nearest neighbor in the set to p; null if set is empty 215 | if(this.numNodes==0) return null; 216 | return nearestRec(p, root, root.point.distanceSquaredTo(p)).point; 217 | }*/ 218 | } 219 | --------------------------------------------------------------------------------