算法导论第四版学习——习题五Kd-Tree

题目正文:

http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html

作业难点:

如何组织自己的数据结构是本道题的最难点,基本上有思路就肯定可以完成。题目一定要看仔细,基本上2dtree部分已经把实现原理说清楚了。

作业技巧:

1、逐步实现,实现完成后用insert、contain测试下,没问题再写draw,测试没问题再写其余的。

2、重复输入的问题不要忘了

3、range虽然api里写的是all point inside the rectangle,但是你必须把边界上的点也算进去

4、java不像C#可以传参数前面加ref或out,所以必须在递归的时候返回Point

5、比较容易疏忽的是子节点在分界线上部或者下部的处理是不一样的,你认为左边是右子树,上边是左子树都没关系。最后结果不会有问题

代码参考:

(这是我自己亲测100分的答案,不代表写得最好,请在自己实在完成不了的时候再看,不然的话做这个题目的意义一点都没有)

 1 import edu.princeton.cs.algs4.Point2D;
 2 import edu.princeton.cs.algs4.RectHV;
 3 import edu.princeton.cs.algs4.SET;
 4 
 5 import java.util.Stack;
 6 
 7 
 8 public class PointSET {
 9     private SET<Point2D> pointSet;
10 
11     public PointSET() // construct an empty set of points 
12      {
13         pointSet = new SET<Point2D>();
14     }
15 
16     private void checkNull(Object obj) {
17         if (obj == null) {
18             throw new NullPointerException();
19         }
20     }
21 
22     public boolean isEmpty() // is the set empty? 
23      {
24         return pointSet.isEmpty();
25     }
26 
27     public int size() // number of points in the set 
28      {
29         return pointSet.size();
30     }
31 
32     public void insert(Point2D p) // add the point to the set (if it is not already in the set)
33      {
34         checkNull(p);
35         pointSet.add(p);
36     }
37 
38     public boolean contains(Point2D p) // does the set contain point p? 
39      {
40         checkNull(p);
41 
42         return pointSet.contains(p);
43     }
44 
45     public void draw() // draw all points to standard draw 
46      {
47         for (Point2D p : pointSet) {
48             p.draw();
49         }
50     }
51 
52     public Iterable<Point2D> range(RectHV rect) // all points that are inside the rectangle 
53      {
54         checkNull(rect);
55 
56         Stack<Point2D> stack = new Stack<Point2D>();
57 
58         for (Point2D p : pointSet) {
59             if ((p.x() >= rect.xmin()) && (p.x() <= rect.xmax()) &&
60                     (p.y() >= rect.ymin()) && (p.y() <= rect.ymax())) {
61                 stack.push(p);
62             }
63         }
64 
65         return stack;
66     }
67 
68     public Point2D nearest(Point2D p) // a nearest neighbor in the set to point p; null if the set is empty 
69      {
70         checkNull(p);
71 
72         Point2D point = null;
73 
74         for (Point2D setp : pointSet) {
75             if ((point == null) ||
76                     (p.distanceSquaredTo(point) > p.distanceSquaredTo(setp))) {
77                 point = setp;
78             }
79         }
80 
81         return point;
82     }
83 
84     public static void main(String[] args) // unit testing of the methods (optional) 
85      {
86     }
87 }
PointSET
  1 import edu.princeton.cs.algs4.In;
  2 import edu.princeton.cs.algs4.Point2D;
  3 import edu.princeton.cs.algs4.RectHV;
  4 import edu.princeton.cs.algs4.StdDraw;
  5 import edu.princeton.cs.algs4.StdOut;
  6 
  7 import java.util.Stack;
  8 
  9 
 10 public class KdTree {
 11     private PointNode root;
 12     private int pointCount;
 13 
 14     public KdTree() // construct an empty set of points 
 15      {
 16         root = null;
 17         pointCount = 0;
 18     }
 19 
 20     private void checkNull(Object obj) {
 21         if (obj == null) {
 22             throw new NullPointerException();
 23         }
 24     }
 25 
 26     public boolean isEmpty() // is the set empty? 
 27      {
 28         return root == null;
 29     }
 30 
 31     public int size() // number of points in the set 
 32      {
 33         return pointCount;
 34     }
 35 
 36     public void insert(Point2D p) // add the point to the set (if it is not already in the set)
 37      {
 38         checkNull(p);
 39 
 40         if (root == null) {
 41             root = new PointNode(p, null, false);
 42             pointCount++;
 43         } else {
 44             PointNode current = root;
 45 
 46             while (true) {
 47               if (current.value.compareTo(p) == 0) {
 48                 return;
 49               }
 50                 if (current.isAtLeftSideOfNode(p)) {
 51                     if (current.left == null) {
 52                         current.left = new PointNode(p, current, true);
 53                         pointCount++;
 54                         break;
 55                     } else {
 56                         current = current.left;
 57                     }
 58                 } else {
 59                     if (current.right == null) {
 60                         current.right = new PointNode(p, current, false);
 61                         pointCount++;
 62                         break;
 63                     } else {
 64                         current = current.right;
 65                     }
 66                 }
 67             }
 68         }
 69     }
 70 
 71     public boolean contains(Point2D p) // does the set contain point p? 
 72      {
 73         checkNull(p);
 74 
 75         PointNode current = root;
 76 
 77         while (current != null) {
 78             if (current.value.compareTo(p) == 0) {
 79                 return true;
 80             } else if (current.isAtLeftSideOfNode(p)) {
 81                 current = current.left;
 82             } else {
 83                 current = current.right;
 84             }
 85         }
 86 
 87         return false;
 88     }
 89 
 90     public void draw() // draw all points to standard draw 
 91      {
 92         if (root != null) {
 93             root.draw(null, false);
 94         }
 95     }
 96 
 97     private void addToStack(Stack<Point2D> stack, PointNode current, RectHV rect) {
 98         
 99         if (!rect.intersects(current.rect)) {
100             return;
101         }
102 
103         if ((current.value.x() >= rect.xmin()) &&
104                 (current.value.x() <= rect.xmax()) &&
105                 (current.value.y() >= rect.ymin()) &&
106                 (current.value.y() <= rect.ymax())) {
107             stack.push(current.value);
108         }
109 
110         if (current.left != null) {
111             addToStack(stack, current.left, rect);
112         }
113 
114         if (current.right != null) {
115             addToStack(stack, current.right, rect);
116         }
117     }
118 
119     private Point2D searchNode(Point2D toSearch, PointNode current,
120         Point2D nearestPoint) {
121         if (nearestPoint == null) {
122             nearestPoint = current.value;
123         }
124 
125         double distance = nearestPoint.distanceSquaredTo(toSearch);
126         double newdistance = current.value.distanceSquaredTo(toSearch);
127 
128         if ((distance >= current.rect.distanceSquaredTo(toSearch)) ||
129                 (distance >= newdistance)) {
130             if (distance > newdistance) {
131                 nearestPoint = current.value;
132             }
133 
134             if ((current.isH && (toSearch.y() > current.value.y())) ||
135                     (!current.isH && (toSearch.x() < current.value.x()))) {
136                 if (current.left != null) {
137                     nearestPoint = searchNode(toSearch, current.left,
138                             nearestPoint);
139                 }
140 
141                 if (current.right != null) {
142                     nearestPoint = searchNode(toSearch, current.right,
143                             nearestPoint);
144                 }
145             } else {
146                 if (current.right != null) {
147                     nearestPoint = searchNode(toSearch, current.right,
148                             nearestPoint);
149                 }
150 
151                 if (current.left != null) {
152                     nearestPoint = searchNode(toSearch, current.left,
153                             nearestPoint);
154                 }
155             }
156         }
157 
158         return nearestPoint;
159     }
160 
161     public Iterable<Point2D> range(RectHV rect) // all points that are inside the rectangle 
162      {
163         checkNull(rect);
164 
165         Stack<Point2D> stack = new Stack<Point2D>();
166         if (root != null)
167           addToStack(stack, root, rect);
168 
169         return stack;
170     }
171 
172     public Point2D nearest(Point2D p) // a nearest neighbor in the set to point p; null if the set is empty 
173      {
174         checkNull(p);
175 
176         Point2D point = null;
177         if (root != null)
178           point = searchNode(p, root, point);
179 
180         return point;
181     }
182 
183     public static void main(String[] args) // unit testing of the methods (optional) 
184      {
185         String filename = args[0];
186         In in = new In(filename);
187 
188         KdTree kdtree = new KdTree();
189 
190         while (!in.isEmpty()) {
191             double x = in.readDouble();
192             double y = in.readDouble();
193             Point2D p = new Point2D(x, y);
194             kdtree.insert(p);
195         }
196 
197         kdtree.draw();
198     }
199 
200     private static class PointNode {
201         private PointNode left;
202         private PointNode right;
203         private RectHV rect;
204         private Point2D value;
205         private boolean isH;
206 
207         public PointNode(Point2D p, PointNode parent, boolean isLeftUp) {
208             value = p;
209             left = null;
210             right = null;
211             if (parent == null) {
212                 isH = false;
213                 rect = new RectHV(0, 0, 1, 1);
214             } else {
215                 isH = !parent.isH;
216 
217                 if (isH) {
218                     if (isLeftUp) {
219                         rect = new RectHV(parent.rect.xmin(),
220                                 parent.rect.ymin(), parent.value.x(),
221                                 parent.rect.ymax());
222                     } else {
223                         rect = new RectHV(parent.value.x(), parent.rect.ymin(),
224                                 parent.rect.xmax(), parent.rect.ymax());
225                     }
226                 } else {
227                     if (isLeftUp) {
228                         rect = new RectHV(parent.rect.xmin(), parent.value.y(),
229                                 parent.rect.xmax(), parent.rect.ymax());
230                     } else {
231                         rect = new RectHV(parent.rect.xmin(),
232                                 parent.rect.ymin(), parent.rect.xmax(),
233                                 parent.value.y());
234                     }
235                 }
236             }
237         }
238 
239         public void draw(PointNode parent, boolean isLeftUp) {
240             StdOut.println(isLeftUp ? "leftup" : "rightdown");
241             StdDraw.setPenColor(StdDraw.BLACK);
242             StdDraw.setPenRadius(0.01);
243             value.draw();
244             StdDraw.setPenRadius();
245 
246             if (parent == null) {
247                 StdDraw.setPenColor(StdDraw.RED);
248                 new Point2D(value.x(), 1).drawTo(new Point2D(value.x(), 0));
249             } else {
250                 StdOut.println(value);
251                 StdOut.println(parent.rect);
252 
253                 if (parent.isH) {
254                     StdDraw.setPenColor(StdDraw.RED);
255                     new Point2D(value.x(), rect.ymin()).drawTo(new Point2D(
256                             value.x(), rect.ymax()));
257                 } else {
258                     StdDraw.setPenColor(StdDraw.BLUE);
259                     new Point2D(rect.xmax(), value.y()).drawTo(new Point2D(
260                             rect.xmin(), value.y()));
261                 }
262             }
263 
264             StdDraw.pause(100);
265 
266             if (left != null) {
267                 left.draw(this, true);
268             }
269 
270             if (right != null) {
271                 right.draw(this, false);
272             }
273         }
274 
275         public boolean isAtLeftSideOfNode(Point2D p) {
276             if (isH) {
277                 return p.y() > value.y();
278             } else {
279                 return p.x() < value.x();
280             }
281         }
282     }
283 }
KdTree
原文地址:https://www.cnblogs.com/enigmaxp/p/5913597.html