【2d-Tree】Kd-tree的特例
来源:互联网 发布:过早的优化是万恶之源 编辑:程序博客网 时间:2024/04/29 15:51
最近在学习coursera上的算法4,讲的确实很精彩,2d-tree的实现是基于二叉查找树(BST),但是其中有有很多小的tricks需要与大家分享。
需要注意的是在node数据结构的选取上:
private Point2D point;private Node left;private Node right;private boolean flag;private RectHV rect;前三个理所当然是链表必备要素,后面flag和rect则是为了方便实现range search和nearest point search所添加,rect为node节点所占据的空间,flag表明当前节点是以x还是y划分。
range search的实现基于以下原理:
首先判断需要搜索的矩形rect是否与root所占据的空间有交集,如果有,判断root是否在rect中,然后向下搜索。
nearest point 的实现
nearest的实现比较好玩,利用二叉树的深度优先搜索配合剪枝!
首先判断目标节点与root所占据空间的最短距离dist是否比best大,如果dist>best,则剪枝。贴出伪代码供大家学习
再给出java实现的代码
package kdtree;import java.util.Set;import java.util.TreeSet;import edu.princeton.cs.algs4.Point2D;import edu.princeton.cs.algs4.RectHV;import edu.princeton.cs.algs4.StdDraw;public class KdTree {private class Node implements Comparable<Node> {private Point2D point;private Node left;private Node right;private boolean flag;private RectHV rect;public Node(Point2D point, boolean flag,RectHV rect){this.point = point;this.flag = flag;this.rect = rect;}public int compareTo(Node that){if(flag){return Double.compare(this.point.x(), that.point.x());}else{return Double.compare(this.point.y(), that.point.y());}}}private Node root;private int size = 0; public KdTree(){ // construct an empty set of points root = null; size = 0; } public boolean isEmpty(){ // is the set empty? return size == 0; } public int size(){ // number of points in the set return size; } public void insert(Point2D p){ // add the point to the set (if it is not already in the set)if(this.size==0) {this.root = new Node(p,true,new RectHV(0,0,1,1));this.size ++;}else if(put (root, p)) this.size ++; } private boolean put(Node root, Point2D p){ Node tmp = new Node(p,!root.flag,null); if(root.point.x() == p.x() && root.point.y() == p.y()) return false; int cmp = root.compareTo(tmp); RectHV newrect = null; if(cmp > 0){ if(root.left == null){ if(root.flag){ newrect = new RectHV(root.rect.xmin(), root.rect.ymin(), root.point.x(), root.rect.ymax()); }else{ newrect = new RectHV(root.rect.xmin(), root.rect.ymin(), root.rect.xmax(), root.point.y()); } tmp.rect = newrect; root.left = tmp; return true; } return put(root.left, p); }else{ if(root.right == null){ if(root.flag){ newrect = new RectHV(root.point.x(), root.rect.ymin(), root.rect.xmax(), root.rect.ymax()); }else{ newrect = new RectHV(root.rect.xmin(), root.point.y(), root.rect.xmax(), root.rect.ymax()); } tmp.rect = newrect; root.right = tmp; return true; } return put(root.right, p); } } public boolean contains(Point2D p){ // does the set contain point p? if(isEmpty()) return false; Node tmp = new Node(p,!root.flag,null); Node x = root; while(x !=null){ int cmp = x.compareTo(tmp); if(cmp > 0) x = x.left; else if((x.point.x() == p.x() && x.point.y() == p.y())) return true; else x = x.right; } return false; } public void draw(){ // draw all points to standard drawif (isEmpty()) return;drawRec(root, 0, 1, 0, 1); } public Iterable<Point2D> range(RectHV rect){ // all points that are inside the rectangle Set<Point2D> pointList = new TreeSet<Point2D>(); rangeRec(root, rect, pointList); return pointList; }private void rangeRec(Node root, RectHV rect, Set<Point2D> set) {if (root == null) return;if (root.rect.intersects(rect)) {if (rect.contains(root.point)) set.add(root.point);rangeRec(root.left, rect, set);rangeRec(root.right, rect, set);}}public Point2D nearest(Point2D p){ // a nearest neighbor in the set to point p; null if the set is emptyif(isEmpty()) return null; return nearest(root, root.point, p); } private Point2D nearest(Node root, Point2D champion, Point2D aim){ //Point2D closest = champion; if(root == null || root.rect.distanceSquaredTo(aim) > champion.distanceSquaredTo(aim)) return champion;double dist = root.point.distanceSquaredTo(aim);if (dist < champion.distanceSquaredTo(aim)){champion = root.point;}Node near, far;if((root.flag && (aim.x() < root.point.x())) || (!root.flag && (aim.y() < root.point.y()))){ near = root.left; far = root.right; } else { near = root.right; far = root.left; } champion = nearest(near, champion,aim); champion = nearest(far, champion,aim);return champion; } /* public Point2D nearest(Point2D p) { if (root == null) return null; Point2D retp = null; double mindis = Double.MAX_VALUE; Queue<Node> queue = new Queue<Node>(); queue.enqueue(root); while (!queue.isEmpty()) { Node x = queue.dequeue(); double dis = p.distanceSquaredTo(x.point); if (dis < mindis) { retp = x.point; mindis = dis; } if (x.left != null && x.left.rect.distanceSquaredTo(p) < mindis) queue.enqueue(x.left); if (x.right != null && x.right.rect.distanceSquaredTo(p) < mindis) queue.enqueue(x.right); } return retp; }*/ private void drawRec(Node root, double minX, double maxX, double minY, double maxY) {if (root == null) return;StdDraw.setPenRadius(.001);if (root.flag) {StdDraw.setPenColor(StdDraw.RED);StdDraw.line(root.point.x(), minY, root.point.x(), maxY);drawRec(root.left, minX, root.point.x(), minY, maxY);drawRec(root.right, root.point.x(), maxX, minY, maxY);} else {StdDraw.setPenColor(StdDraw.BLUE);StdDraw.line(minX, root.point.y(), maxX, root.point.y());drawRec(root.left, minX, maxX, minY, root.point.y());drawRec(root.right, minX, maxX, root.point.y(), maxY);}StdDraw.setPenColor(StdDraw.BLACK);StdDraw.setPenRadius(.01);root.point.draw();} public static void main(String[] args){ // unit testing of the methods (optional) }}
0 0
- 【2d-Tree】Kd-tree的特例
- 2D KD-Tree实现
- kd-tree的实现
- Kd-tree的用法
- KD-tree的理解
- kd-tree
- KD Tree
- KD Tree
- kd-tree
- kd-tree
- kd-tree
- kd tree
- KD-Tree
- Kd-tree
- kd-tree
- kd-tree
- kd-tree
- kd-tree
- 鲁能携手沃美影城首度进军天津市场
- Python字符串分割命令split
- 【日记】新工作狂
- Windows下搜索设置
- 使用Disk2VHD进行P2V转换需知的一些事
- 【2d-Tree】Kd-tree的特例
- python异常(待补)
- linux grep 查找制表符\t的方法
- LeetCode 439. Ternary Expression Parser
- SpringMVC从Controller跳转到另一个Controller
- Activiti工作流(一)之基本操作介绍
- Bundle.setClassLoader()方法解析 BootClassLoader PathClassLoader
- Linux 下五个最佳的 FPS 游戏发布啦!
- 一个android app打开另外一个app,并传替数据(个人学习笔记)