C++ 在KDTree中查找最近的邻居-如何处理检查其他树的情况?
我正在尝试一个KDTree类,它涉及到寻找最近的邻居。我想我知道如何遍历到叶节点,然后计算当前节点。但我对如何编写算法检查另一子树上可能存在任何点的部分感到迷茫。以下是我到目前为止对该方法的了解:C++ 在KDTree中查找最近的邻居-如何处理检查其他树的情况?,c++,recursion,kdtree,C++,Recursion,Kdtree,我正在尝试一个KDTree类,它涉及到寻找最近的邻居。我想我知道如何遍历到叶节点,然后计算当前节点。但我对如何编写算法检查另一子树上可能存在任何点的部分感到迷茫。以下是我到目前为止对该方法的了解: template <int Dim> Point<Dim> KDTree<Dim>::nearestNeighbor(const Point<Dim>& query, const Point<Dim>& current_bes
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;
}
模板
点KDTree::最近的邻居(常数点和查询、常数点和当前最佳、整数左、整数右、整数维)常数{
//基本情况:到达叶节点
如果(左==右){
if(shouldReplace(查询、当前_最佳、树[左]){
返回树[左];
}
返回当前最佳值;
}
int中位数_指数=(左+右)/2;
//检查右子树
if(smallerDimVal(当前最佳、查询、维度)){
当前最佳=最近的邻居(查询,当前最佳,中位数索引+1,右,(维度+1)%Dim);
}
//检查左子树
if(smallerDimVal(查询、当前\最佳、维度)){
当前最佳=最近的邻居(查询,当前最佳,左侧,中位数索引-1,(维度+1)%Dim);
}
//检查当前节点(执行所有递归之前我们所在的节点)
if(shouldReplace(查询、当前最佳、树[中间值索引]){
当前_最佳=树[中位数_指数];
}
//检查其他子树是否可能包含更接近的值
if(pow(查询[curDim]-树[median_index][curDim])=Dim){
返回false;
}
//如果curDim处第一个点的坐标等于
//在curDim返回第二个点的值,然后返回第一个值是否小于第二个值。
if(第一个[curDim]==第二个[curDim]){
返回(第一次<第二次);
}
//如果坐标值不同,则如果
//k处的第一个点小于k处第二个点的坐标。
返回(第一个[curDim]<第二个[curDim]);
}
模板
bool KDTree::shouldReplace(常量点和目标,
const Point¤tBest,
常数点和电位)常数
{
int target_current_distance=0;
int目标电位距离=0;
对于(int i=0;i
编辑:已解决。还修改了方法签名
template<int Dim>
typename KDTree<Dim>::KDTreeNode* KDTree<Dim>::nearestNeighbor(const Point<Dim>& query, int dimension, KDTreeNode* subroot) const {
//Base case: Query point is a point in the tree
if (query == subroot->point) {
return subroot;
}
//Base case: Subroot is a leaf
if (subroot->left == NULL && subroot->right == NULL) {
return subroot;
}
KDTreeNode* nearest_node;
bool recursed_left = false;
//Recursive case: Query point at current dimension is less than the point of the subroot at current dimension
if (smallerDimVal(query, subroot->point, dimension)) {
if (subroot->left != NULL) {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->left);
recursed_left = true;
}
else {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->right);
}
}
//Recursive case: Query point at current dimension is greater than the point of the subroot at current dimension
else {
if (subroot->right != NULL) {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->right);
}
else {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->left);
recursed_left = true;
}
}
//Check if current root is closer
if (shouldReplace(query, nearest_node->point, subroot->point)) {
nearest_node = subroot;
}
//Radius between query point and the point currently labeled as nearest
double radius = calculateDistance(query, nearest_node->point);
//Split distance on plane
double split_distance = pow(subroot->point[dimension] - query[dimension], 2);
if (radius >= split_distance) {
if (recursed_left) {
if (subroot->right != NULL) {
KDTreeNode* temp_nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->right);
if (shouldReplace(query, nearest_node->point, temp_nearest_node->point)) {
nearest_node = temp_nearest_node;
}
}
}
else {
if (subroot->left != NULL) {
KDTreeNode* temp_nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->left);
if (shouldReplace(query, nearest_node->point, temp_nearest_node->point)) {
nearest_node = temp_nearest_node;
}
}
}
}
return nearest_node;
}
模板
类型名KDTree::KDTreeNode*KDTree::nearestNeighbor(常量点和查询、int维、KDTreeNode*subroot)常量{
//基本情况:查询点是树中的一个点
如果(查询==子轨迹->点){
返回副轨道;
}
//基本情况:Subroot是一个叶
if(子轨迹->左==NULL&&subroot->右==NULL){
返回副轨道;
}
KDTreeNode*最近的_节点;
布尔递归_左=假;
//递归情况:当前维度的查询点小于当前维度的子轨迹点
if(smallerDimVal(查询,子轨迹->点,尺寸)){
如果(子轨迹->左!=空){
最近的节点=最近的邻居(查询,(维度+1)%Dim,子轨迹->左);
递归左=真;
}
否则{
最近的节点=最近的邻居(查询,(维度+1)%Dim,子轨迹->右侧);
}
}
//递归情况:当前维度的查询点大于当前维度的子轨迹点
否则{
如果(子轨迹->右!=空){
最近的节点=最近的邻居(查询,(维度+1)%Dim,子轨迹->右侧);
}
否则{
最近的节点=最近的邻居(查询,(维度+1)%Dim,子轨迹->左);
递归左=真;
}
}
//检查当前根是否更近
if(应替换(查询,最近的_节点->点,子轨迹->点)){
最近的_节点=子轨道;
}
//查询点与当前标记为最近的点之间的半径
双半径=计算距离(查询,最近的_节点->点);
//平面上的分裂距离
双分割距离=pow(子轨迹->点[dimension]-查询[dimension],2);
如果(半径>=分割距离){
if(递归左){
如果(子轨迹->右!=空){
KDTreeNode*temp_nearest_node=nearestNeighbor(查询,(维度+1)%Dim,subroot->right);
if(应该替换(查询,最近的节点->点,临时最近的节点->点)){
最近的_节点=临时_最近的_节点;
}
}
}
否则{
如果(子轨迹->左!=空){
KDTreeNode*temp_nearest_node=nearestNeighbor(查询,(维度+1)%Dim,subroot->left);
if(应该替换(查询,最近的节点->点,临时最近的节点->点)){
最近的_节点=临时_最近的_节点;
}
}
}
}
返回最近的_节点;
}
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);
}
template<int Dim>
typename KDTree<Dim>::KDTreeNode* KDTree<Dim>::nearestNeighbor(const Point<Dim>& query, int dimension, KDTreeNode* subroot) const {
//Base case: Query point is a point in the tree
if (query == subroot->point) {
return subroot;
}
//Base case: Subroot is a leaf
if (subroot->left == NULL && subroot->right == NULL) {
return subroot;
}
KDTreeNode* nearest_node;
bool recursed_left = false;
//Recursive case: Query point at current dimension is less than the point of the subroot at current dimension
if (smallerDimVal(query, subroot->point, dimension)) {
if (subroot->left != NULL) {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->left);
recursed_left = true;
}
else {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->right);
}
}
//Recursive case: Query point at current dimension is greater than the point of the subroot at current dimension
else {
if (subroot->right != NULL) {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->right);
}
else {
nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->left);
recursed_left = true;
}
}
//Check if current root is closer
if (shouldReplace(query, nearest_node->point, subroot->point)) {
nearest_node = subroot;
}
//Radius between query point and the point currently labeled as nearest
double radius = calculateDistance(query, nearest_node->point);
//Split distance on plane
double split_distance = pow(subroot->point[dimension] - query[dimension], 2);
if (radius >= split_distance) {
if (recursed_left) {
if (subroot->right != NULL) {
KDTreeNode* temp_nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->right);
if (shouldReplace(query, nearest_node->point, temp_nearest_node->point)) {
nearest_node = temp_nearest_node;
}
}
}
else {
if (subroot->left != NULL) {
KDTreeNode* temp_nearest_node = nearestNeighbor(query, (dimension + 1) % Dim, subroot->left);
if (shouldReplace(query, nearest_node->point, temp_nearest_node->point)) {
nearest_node = temp_nearest_node;
}
}
}
}
return nearest_node;
}