在KD树中查找最近邻居

时间:2014-12-05 03:30:27

标签: c++ nearest-neighbor kdtree

警告:相当长的问题,也许太久了。如果是的话,我道歉。

我正在研究一个涉及最近邻居搜索kd树的程序(在这个例子中,它是一个具有3961个单独点的11维树)。我们刚刚了解了它们,虽然我很好地掌握了树的作用,但是当谈到最近邻搜索时,我感到非常困惑。

我已经设置了一个2D点阵列,每个点都包含一个质量和一个位置,看起来像这样。

struct point{
  double quality;
  double location;
}

// in main
point **parray; 
// later points to an array of [3961][11] points

然后我翻译了数据,使其具有零均值,并将其重新调整为单位方差。我不会发布代码,因为它对我的问题不重要。之后,我按照随机顺序将点构建到树中:

struct Node {
  point *key;
  Node *left;
  Node *right;
  Node (point *k) { key = k; left = right = NULL; }
};

Node *kd = NULL;
// Build the data into a kd-tree
random_shuffle(parray, &parray[n]);
for(int val=0; val<n; val++) {
  for(int dim=1; dim<D+1; dim++) {
    kd = insert(kd, &parray[val][dim], dim);
  }
}

非常标准的东西。如果我错误地使用了random_shuffle(),或者如果树的结构存在任何内在错误,请告诉我。它应该改变混淆的第一个维度,同时保留每个维度的11个维度并且不受影响。

现在我正在使用neighbor()函数,这就是我感到困惑的地方。

neighbor()函数(后半部分是伪代码,我坦率地不知道从哪里开始):

Node *neighbor (Node *root, point *pn, int d, 
                Node *best, double bestdist) {
  double dist = 0;
  // Recursively move down tree, ignore the node we are comparing to
  if(!root || root->key == pn) return NULL;

  // Dist = SQRT of the SUMS of SQUARED DIFFERENCES of qualities
  for(int dim=1; dim<D+1; dim++) 
    dist += pow(pn[d].quality - root->key->quality, 2);
  dist = sqrt(dist);

  // If T is better than current best, current best = T
  if(!best || dist<bestdist) {
    bestdist = dist;
    best = root;
  }

  // If the dist doesn't reach a plane, prune search, walk back up tree
  // Else traverse down that tree

  // Process root node, return
}

这是main()中对邻居的调用,大部分是未完成的。我不确定main()中应该是什么以及neighbor()函数应该是什么:

// Nearest neighbor(s) search
double avgdist = 0.0;
// For each neighbor
for(int i=0; i<n; i++) {
  // Should this be an array/tree of x best neighbors to keep track of them?
  Node *best;
  double bestdist = 1000000000;
  // Find nearest neighbor(s)? 
  for(int i=0; i<nbrs; i++) {
    neighbor(kd, parray[n], 1, best, &bestdist);
  }
  // Determine "distance" between the two?
  // Add to total dist?
  avgdist += bestdist;
}
// Average the total dist
//  avgdist /= n;

正如您所看到的,我坚持使用最后两段代码。我已经在这几天wra my my,,,,,,,,,,,and and and and and它很快到期,所以当然任何和所有的帮助都是值得赞赏的。提前谢谢。

1 个答案:

答案 0 :(得分:1)

kd-tree不涉及改组。

事实上,您将需要使用排序(或更好,快速选择)来构建树。

首先解决 最近邻居(1NN)。一旦你有这个部分工作,通过保留一堆顶级候选者,并使用第k个点进行修剪,应该相当清楚如何找到kNN。