zoukankan      html  css  js  c++  java
  • Programming Assignment 5: Kd-Trees

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

    1. 问题重述

    这个问题其实就是Kd-Trees那节课讲的内容,按照老师的思路来实现就好了。

    这个问题就是在一个平面上有N个点,需要实现两个功能。

    1. 在给定一个平面内区域,让你寻找在区域中点的个数。
    2. 给定一个点,寻找离这个点最近的M个点

    2. 分析

    题目要求用两种方法求解,一种暴力方法,一种2d-Tree。

    2.1 暴力搜索

    功能1,将每个点都和需要搜索的区域比较。

    功能2,计算给定点和每个点的距离,拿个优先队列存M个。

    点的插入、删除使用红黑树,时间就能满足O(logn)。两个功能就是O(N)。

    2.2 构建2d-Tree

    本以为就按照课程讲的做就是了。结果实际写的过程中遇到了好多好多问题。

    那这里就把思路详细的写出来了。

    2d-Tree是一个变种的BST。

    2.2.1 构造Node

    包括Node的坐标、Node所在的矩形、Node的左/下子树、Node的右/上子树。

    2.2.2 insert函数

    插入的时候使用迭代的思想,将新的点插入到一个节点,然后再节点中向对应的子树插入此节点。当遇到空的子树时,插入新点。

    难点1,由于不同层分割区域的方式不同,所以需要在插入函数中加入一个参数i记录所在层,通过i % 2来判断分割方式,选择比较对象x或y。

    难点2,插入时存在两个假设,1.对于落在分割线上的点,假设点分在右/上子树;2.相同坐标的点只插入一次。理清楚这两个假设需要费些时间,要分清分割线上的点,和相同的点。

    2.2.3 contain函数

    contain函数的搜索过程和insert找插入点的过程一致,需要注意的就是区分相同点和落在分割线上的点。另外要注意的是,不要自己写判断点是否包含在矩形中,直接用矩形的成员函数。

    2.2.4 range函数

    递归调用,每次先判断range矩形是否在当前Node的矩形里,不在则将当前Node和其子树剪枝。若在矩形里,则继续搜索子树。

    2.2.5 nearest函数

    重头戏来了,坑了我最久时间的函数。

    这个问题最难的点在于

    1. 需要判断query点在Node的哪一侧。因为需要从query点所在的一侧开始搜索。
    2. 搜索完一侧之后,另一侧是否剪枝。因为Node两侧子树还可能不存在。而且判题系统不允许自己使用distanceTo来判断点到切割线的距离,只能使用子树的矩形的contain函数。就需要先判断两侧子树是否存在。

    然后我就把自己绕晕在这几个判断条件里了。

    现在来清楚的理一下流程。依旧使用递归的方法。

    1. 传入节点,将节点和最短节点比较,更新最短节点。这里,第一次使用根节点作为最短节点,并传入根节点。
    2. 判断点在哪侧。根据切割方向,将Node里的x/y与query点的x/y来比较。
    3. 若在左/下侧,进入流程3。若在右/上侧,进入流程4。
    4. 判断左侧是否有节点,如果有节点,将节点传入nearest函数。然后判断右侧是否存在节点,若不存在则直接返回;若存在,则判断左侧距离右侧节点所在矩形的距离是否是否大于最短距离,若大于,则返回,否则搜索右侧。
    5. 判断右侧是否有节点,如果有节点,将节点传入nearest函数。然后判断左侧是否存在节点,若不存在则直接返回;若存在,则判断右侧距离左侧节点所在矩形的距离是否是否大于最短距离,若大于,则返回,否则搜索左侧。

    流程图如下图所示。

    nearest函数流程图

  • 相关阅读:
    angular 个人零点学习
    angularjs 五大关键点
    OA项目学习总结
    oa
    时间插件
    angular js模态框
    搜索
    xianduanshu
    o-o
    paibingbuzhen
  • 原文地址:https://www.cnblogs.com/huipengly/p/9733057.html
Copyright © 2011-2022 走看看