├── .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 |
--------------------------------------------------------------------------------