zoukankan      html  css  js  c++  java
  • 算法导论第四版学习——习题五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
  • 相关阅读:
    vue-cli生成的重要代码详解
    vuex初探
    vue-router笔记
    新技术的学习
    图片优化方法(有时间看看)
    关于老教授之家项目的思考 && 中国互联网+大赛培训
    If you are tired...
    微信公众平台开发初探
    winscp介绍与使用
    获取当前服务器信息
  • 原文地址:https://www.cnblogs.com/enigmaxp/p/5913597.html
Copyright © 2011-2022 走看看