算法导论第四版学习——习题五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

时间: 2024-10-19 21:15:09

算法导论第四版学习——习题五Kd-Tree的相关文章

算法导论第四版学习——习题三Collinear Points

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 作业难点: 1.仔细思考会感觉有很多实现方法,但是如果没有适当使用排序,算法时间复杂度就会轻易超过要求.(包括暴力算法) 2.隐含需要实现自己的数据结构用来组织“线”的集合,当然也可以用Stack或者Queue或者LinkedList,但是我个人是自己实现的. 3.由于一条线段只能出现一次,所以有一个去重的问题.(最难) 作业技巧: 1.基本按照题目的先

算法导论第四版学习——习题一Percolation

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 作业难点: 1.backwash(倒灌)的判断,如果不使用另一个WeightedUnionFind对象,要在要求的时间和空间范围内实现是很困难的 和论坛里的学生一样,尝试只只使用上部的虚拟节点,下部判断联通使用循环+break,提交后不满足时间复杂度要求 你也可以不考虑backwash这种情况,因为backwash对连通性并没有直接影响 2.Unio

算法导论第四版学习——习题二Deques and Randomized Queues

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/queues.html 作业难点: 1.选择使用链表还是数组,将会是第一个问题,选择合适会减少很多工作量. 2.并行从RandomizedQueue中取两个枚举,这两个枚举必须是不一样的,所以有很多偷懒的“伪随机”是行不通的. 3.SubSet仅需K存储而不是N存储,即可实现.(这个我也没想到方法实现) 作业技巧: 1.可遍数组和邻接节点两种数据结构都已经给你了,你只要改改,基本上实

算法导论第四版学习——习题四8 Puzzle

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 作业难点: 1.如何验证Puzzle是否可解?题目中有提示,如果相邻两个格子交换后得到的“Twin Puzzle”进行求解,如果Twin有解那么原始Puzzle就无解. 作业技巧: 1.checklist提到把Twin Puzzle和Puzzle放在一个Priority Queue中,其实就是在设计自己的Node数据结构的时候加一个boolean类型标识是否

算法第四版学习笔记之快速排序 QuickSort

软件:DrJava 参考书:算法(第四版) 章节:2.3快速排序(以下截图是算法配套视频所讲内容截图) 1:快速排序 2:

马克思主义基本原理概论》学生辅学读本(第四版)习题答案

马克思主义基本原理概论 学生辅学读本(第四版)习题答案 逄锦聚<马克思主义基本原理概论>学生辅学读本(第四版)习题答案?本书是马克思主义理论研究和建设工程重点教材<马克思主义基本原理概论>(2013年修订版)的配套用书,根据党的十八大精神,进行了相应内容的修改.本书依据教材的逻辑体系,从适合学生学习的角度出发进行内容设计,每章包括"明确学习目标"."教师导航分析"."观点案例点评"."游弋大千题海".&

计算机组成原理_第四版课后习题答案(完整版)

计算机组成原理_第四版课后习题答案(完整版) ?第一章 1.?比较数字计算机和模拟计算机的特点. 解:模拟计算机的特点:数值由连续量来表示,运算过程是连续的: 数字计算机的特点:数值由数字量(离散量)来表示,运算按位进行. 两者主要区别见P1?表1.1. 2.?数字计算机如何分类?分类的依据是什么? 解:分类: 数字计算机分为专用计算机和通用计算机.通用计算机又分为巨型机.大型机. 中型机.小型机.微型机和单片机六类. 分类依据:专用和通用是根据计算机的效率.速度.价格.运行的经济性和适应性来划

算法(第四版)C#题解&mdash;&mdash;1.3.49 用 6 个栈实现一个 O(1) 队列

因为这个解法有点复杂,因此单独开一贴介绍. <算法(第四版)>中的题目是这样的: 1.3.49 栈与队列.用有限个栈实现一个队列,保证每个队列操作(在最坏情况下)都只需要常数次的栈操作. 那么这里就使用六个栈来解决这个问题. 这个算法来自于这篇论文. 原文里用的是 Pure Lisp,不过语法很简单,还是很容易看懂的. 先导知识--用两个栈模拟一个队列 如何使用两个栈来模拟一个队列操作? 这是一道很经典的题目,答案也有很多种,这里只介绍之后会用到的一种方法. 首先我们有两个栈,H 和 T,分别

ubuntu命令行下java工程编辑与算法(第四版)环境配置

ubuntu命令行下java工程编辑与算法(第四版)环境配置 java 命令行 javac java 在学习算法(第四版)中的实例时,因需要安装配套的java编译环境,可是在编译java文件的时候总是出各种错误,特在此总结一下. ubuntu下java环境配置 由于网上教程比较多,而且也较全面,特此摆放一个链接,跟着此教程总就可以配置好oracle的java jdk,如果想更加省事,直接在命令行下键入java,会提示安装各种开源java jdk,只需要一个命令即可: sudo apt-get i