This problem is a kind of closest pair between two disjoint set. Upperside picture
here is one more solution. What it basically does is loads both of the set of points into two kd tree instances (which have built mechanism for slicing the tree on x and y axis) and then navigates through both of the trees by checking each node if the distances between the two less than the distance between the prior nodes, if yes then continue until no two nodes can be found with the mutual distance less than any other.
the below code prints the distances found while navigating between the nodes and prints them. The both set of points are also be visualized to see the correctness of the algorithem.
This code can correctly find the nearest nodes regardless whether one set is nested, on right, left, up or downward of the other,
#include
using namespace std;
int const k=2; // the number of dimensions
double min_distance = 10000; // set a large default value, in this example all distance will be shorter than this.
double distance(int arr[], int arr2[])
{
return sqrt(pow(arr2[0] - arr[0], 2) + pow(arr2[1] - arr[1], 2));
}
struct Node {
int point[k];
Node *left, *right;
Node()
{
left = right = NULL;
}
};
// A method to create a node of K D tree
struct Node* newNode(int arr[])
{
struct Node* temp = new Node;
for (int i = 0; ipoint[i] = arr[i];
return temp;
}
Node * insertNode(Node * node, int arr[], int d)
{
if (node == NULL)
return newNode(arr);
int dim = d%k;
if (node->point[dim] > arr[dim])
{
node->left = insertNode(node->left, arr, dim + 1);
}
else
{
node->right = insertNode(node->right, arr, dim + 1);
}
return node;
}
Node * Nearest=NULL;
Node * FindnearestNode(Node * head1, int arr[], int d)
{
// if empty tree, return
if (head1 == NULL)
return NULL;
// check for each tree.
if (min_distance > distance(head1->point, arr))
{
min_distance = distance(head1->point, arr);
Nearest = head1;
}
if (head1->left == NULL && head1->right == NULL)
return head1;
// findout current dimension, in this case it either x or y i.e. 0 or 1
int dim = d%k;
// navigate through the tree as if inserting to a new member (to remain to the nearest member in closeness). in the path for insert it will find the nearest member.
if (head1->right && head1->point[dim] < arr[dim]) return FindnearestNode(head1->right, arr, d+1);
else if(head1->left && head1->point[dim] > arr[dim] )
return FindnearestNode(head1->left, arr, d+1);
return Nearest;
}
int main()
{
int const an = 10;
int const bn = 10;
int ax[an] = { 34,55,11,79,77,65,3,9,5,66 };
int ay[an] = { 5, 6, 7, 9, 32,3,15,7,10,35 };
int bx[bn] = { 5,35,4,41,32,64,41,54,87,3 };
int by[bn] = { 23,33,17,15,32,22,33,23,21,32 };
Node * head1=NULL;
Node * head2 = NULL;
double Final_Min_Distance = min_distance;
// fill the K-D trees with the two dimensional data in two trees.
for (int i = 0; i < an; i++)
{
int temp[k];
temp[0] = ax[i];
temp[1] = ay[i];
head1=insertNode(head1, temp, 0);
temp[0] = bx[i];
temp[1] = by[i];
head2=insertNode(head2, temp, 0);
}
Node * AnearB=NULL;
Node * BnearA = NULL;
min_distance = 1000;
Final_Min_Distance = min_distance;
for (int i = 0; i < an; i++) { int temp[k]; temp[0] = bx[i]; temp[1] = by[i]; Node * Nearer2 = FindnearestNode(head1, temp, 0); if (Final_Min_Distance > min_distance)
{
BnearA = Nearer2;
Final_Min_Distance = min_distance;
}
cout << " distance of B (" << temp[0] << "," << temp[1] << ") to nearest A (" << BnearA->point[0] << "," << BnearA->point[1] << ") distance:" << Final_Min_Distance << endl;
min_distance = 1000;
}
cout << "Minimum Distance is " << Final_Min_Distance< min_distance)
{
AnearB = Nearer2;
Final_Min_Distance = min_distance;
}
cout << " distance of A (" << temp[0] << "," << temp[1] << ") to nearest B (" << AnearB->point[0] << "," << AnearB->point[1] << ") distance:" << Final_Min_Distance << endl;
min_distance = 1000;
}
cout << "Minimum Distance is " << Final_Min_Distance;
system("pause");
}
https://tahirnaeem.net/finding-closest-pair-of-points-in-two-disjoint-sets-of-points