首页 > 代码库 > 算法导论第四版学习——习题五Kd-Tree

算法导论第四版学习——习题五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 =http://www.mamicode.com/ 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

 

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