【发布时间】:2021-06-11 03:00:21
【问题描述】:
我正在尝试处理涉及查找最近邻居的 KDTree 类。我想我知道如何执行向下遍历到叶节点然后评估当前节点的部分。但是我对如何编写算法检查另一个子树上可能存在任何点的部分感到非常迷茫。以下是我目前对该方法的了解:
template <int Dim>
Point<Dim> KDTree<Dim>::nearestNeighbor(const Point<Dim>& query, const Point<Dim>& current_best, int left, int right, int dimension) const {
//Base case: Reached a leaf node
if (left == right) {
if (shouldReplace(query, current_best, tree[left])) {
return tree[left];
}
return current_best;
}
int median_index = (left + right) / 2;
//Check right subtree
if (smallerDimVal(current_best, query, dimension)) {
current_best = nearestNeighbor(query, current_best, median_index + 1, right, (dimension + 1) % Dim);
}
//Check left subtree
if (smallerDimVal(query, current_best, dimension)) {
current_best = nearestNeighbor(query, current_best, left, median_index - 1, (dimension + 1) % Dim);
}
//Check the current node (the node we were at before doing all the recursion)
if (shouldReplace(query, current_best, tree[median_index])) {
current_best = tree[median_index];
}
//Check if the other subtree could possibly contain a value closer
if (pow(query[curDim] - tree[median_index][curDim]) <= calculateDistance(query, current_best)) {
//What to do here????
}
return current_best;
}
这些是最近邻函数使用的类中的函数以及调用它的初始方法。我还提供了 TreeNode 结构供参考:
struct KDTreeNode
{
Point<Dim> point;
KDTreeNode *left, *right;
KDTreeNode() : point(), left(NULL), right(NULL) {}
KDTreeNode(const Point<Dim> &point) : point(point), left(NULL), right(NULL) {}
};
template <int Dim>
bool KDTree<Dim>::smallerDimVal(const Point<Dim>& first,
const Point<Dim>& second, int curDim) const
{
if (curDim < 0 || curDim >= Dim) {
return false;
}
//If the coordinate of the first point at curDim is equal to the coordinate
//of the second point at curDim, then return whether or not first is less than second.
if (first[curDim] == second[curDim]) {
return (first < second);
}
//If the coordainte values differ, then return true if the coordinate of the
//first point at k is less than the coordinate of the second point at k.
return (first[curDim] < second[curDim]);
}
template <int Dim>
bool KDTree<Dim>::shouldReplace(const Point<Dim>& target,
const Point<Dim>& currentBest,
const Point<Dim>& potential) const
{
int target_current_distance = 0;
int target_potential_distance = 0;
for (int i = 0; i < Dim; i++) {
target_current_distance += ((currentBest[i] - target[i]) * (currentBest[i] - target[i]));
}
for (int i = 0; i < Dim; i++) {
target_potential_distance += ((potential[i] - target[i]) * (potential[i] - target[i]));
}
//Return true if the potential point is closer.
if (target_potential_distance != target_current_distance) {
return (target_potential_distance < target_current_distance);
}
else {
return (potential < currentBest);
}
}
template <int Dim>
double KDTree<Dim>::calculateDistance(const Point<Dim>& first, const Point<Dim>& second) const {
double distance = 0;
for (int i = 0; i < Dim; i++) {
distance += ((second[i] - first[i]) * (second[i] - first[i]));
}
return distance;
}
template <int Dim>
Point<Dim> KDTree<Dim>::findNearestNeighbor(const Point<Dim>& query) const
{
//query is the point where we want to find the closest distance to in the tree
int median_index = (tree.size() - 1) / 2;
return nearestNeighbor(query, tree[median_index], 0, tree.size() - 1, 0);
}
【问题讨论】: