【问题标题】:Kd-Tree flawed K nearest neighborKd-Tree 有缺陷的 K 最近邻
【发布时间】:2017-03-31 11:07:52
【问题描述】:

免责声明:以下代码中有一些不好的做法

您好,关于如何正确格式化我的 KD 树 K 最近邻搜索,我有几个问题。这是我的函数的一个示例。

void nearest_neighbor(Node *T, int K) {
  if (T == NULL) return;
  nearest_neighbor(T->left, K); 
  //do stuff find dist etc
  if(?)nearest_neighbor(T->right, K);  
 }

此代码令人困惑,因此我将尝试对其进行解释。我的函数只接受 k 值和节点 T。我要做的是找到当前节点与结构中每个其他值之间的距离。这些都有效,我遇到的问题是了解何时以及如何调用递归调用 nearest_neighbor(T->left/T->right,K) 我知道我打算将调用修剪到右侧,但我'我不知道该怎么做。顺便说一下,这是一个多维 KD 树。任何更好的例子的指导将不胜感激。

【问题讨论】:

    标签: c++ algorithm data-structures nearest-neighbor kdtree


    【解决方案1】:

    一般的想法是保持一个最接近目标的全局点,用新发现的点进行更新,并且永远不会下降到一个不可能包含比已找到的最近的目标更近的点的 n 边形。我将用 C 而不是 C++ 来展示它。您可以轻松地转换为面向对象的形式。

    #define N_DIM <k for the k-D tree>
    
    typedef float COORD; 
    
    typedef struct point_s {
      COORD x[N_DIM];
    } POINT;
    
    typedef struct node_s {
      struct node_s *lft, *rgt;
      POINT p[1];
    } NODE;
    
    POINT target[1];    // target for nearest search
    POINT nearest[1];   // nearest found so far
    POINT b0[1], b1[1]; // search bounding box
    
    bool prune_search() {
      // Return true if no point in the bounding box [b0..b1] is closer
      // to the target than than the current value of nearest.
    }
    
    void search(NODE *node, int dim);
    
    void search_lft(NODE *node, int dim) {
      if (!node->lft) return;
      COORD save = b1->p->x[dim];
      b1->p->x[dim] = node->p->x[dim];
      if (!prune_search()) search(node->lft, (dim + 1) % N_DIM);
      b1->p->x[dim] = save; 
    }
    
    void search_rgt(NODE *node, int dim) {
      if (!node->rgt) return;
      COORD save = b0->p->x[dim];
      b0->p->x[dim] = node->p->x[dim];
      if (!prune_search()) search(node->rgt, (dim + 1) % N_DIM);
      b0->p->x[dim] = save; 
    }
    
    void search(NODE *node, int dim) {
      if (dist(node->p, target) < dist(nearest, target)) *nearest = *node->p;
      if (target->p->x[dim] < node->p->x[dim]) {
        search_lft(node, dim);
        search_rgt(node, dim);
      } else {
        search_rgt(node, dim);
        search_lft(node, dim);
      }
    }
    
    /** Set *nst to the point in the given kd-tree nearest to tgt. */
    void get_nearest(POINT *nst, POINT *tgt, NODE *root) {     
      *b0 = POINT_AT_NEGATIVE_INFINITY;
      *b1 = POINT_AT_POSITIVE_INFINITY;
      *target = *tgt;
      *nearest = *root->p;
      search(root, 0);
      *nst = *nearest;
    }
    

    请注意,这不是最经济的实施方式。为简单起见,它会进行一些不必要的最近更新和修剪比较。但它的渐近性能与 kd-tree NN 的预期一致。在你得到这个工作之后,你可以把它作为一个基本的实现来挤出额外的比较。

    【讨论】:

      【解决方案2】:

      我建议你像Wikipedia 所说的那样实施,对于你的具体问题,这个:

      从根节点开始,算法向下移动 递归地,就像如果搜索点是 被插入(即它向左或向右取决于 点小于或大于拆分中的当前节点 尺寸)。

      回答问题。当然你可以记住这个形象:

      如果您有更多像示例中那样的两个维度,您只需在第一个维度中拆分,然后在第二个维度中,然后在第三个中,然后在第四个中,依此类推,然后您遵循循环策略,所以当你到达最终维度时,你又从第一个维度开始。

      【讨论】:

        猜你喜欢
        • 2012-06-27
        • 1970-01-01
        • 1970-01-01
        • 2020-03-16
        • 2014-04-12
        • 2015-03-17
        • 2012-06-11
        • 2018-03-12
        • 2011-12-06
        相关资源
        最近更新 更多