This article mainly for you in detail the C # through the KD tree to find the nearest point, with a certain reference value, interested in small partners can refer to
This paper first introduces the construction method of Kd-tree, then introduces the search process and code implementation of Kd-tree, and finally gives me a two-dimensional KD tree code implemented by C # language. This is the first tree-shaped data structure I've implemented myself. Understanding will inevitably have deviations, please many treatise.
1. KD Tree Introduction
Kd-tree, or k-dimensional tree, is a high-dimensional indexed tree data structure that is commonly used for nearest neighbor lookups and approximate nearest neighbor lookups in large, high-dimensional data spaces. The KD tree I implemented is a two-dimensional kd-tree. The goal is to find the nearest point in the point set. Reference is Kd-tree's Baidu encyclopedia. And according to the logic of Baidu Encyclopedia to organize the code.
2. The mathematical interpretation of KD tree
3. Method of constructing KD tree
Here is a two-dimensional point set to construct the Kd-tree. Three-dimensional is similar to this.
Data type for each node in the tree:
public class Kdtreenode {//<summary>/// split points// </summary> public Point Pisionpoint {get; set;} <summary>///split type/// </summary> public enumpisiontype pisiontype {get; set;} <summary>///Left Dial hand node/// </summary> public kdtreenode leftchild {get; set;} <summary>/// Right child node/// </summary> public kdtreenode rightchild {get; set;} }
3.1 KD Tree construction logic Flow
Put all the points in set a
The variance xv,y coordinates are calculated for the X coordinate of all points in the collection YV
If XV > YV, the collection A is sorted according to the X coordinate. If YV > XV, the set a is sorted according to the y-coordinate.
Gets the median m of a collection after sorting. The point of the [0,m-2] index is placed in the A1 collection with M as a breakpoint. Place the point of the [M,a.count] index into the collection of A2 (the index of the M point is m-1).
Build node, the value of the node is a[m-1], if the number of nodes in the Operation collection is greater than 1, the left node repeats 2-5 steps for [0,m-2], the right node repeats 2-5 steps for [M,a.count], and vice versa, the node is a leaf node.
3.2 Code Implementation
Private Kdtreenode Createtreenode (list<point> pointlist) { if (Pointlist.count > 0) { //Calculate variance Double xobtainvariance = obtainvariance (Createxlist (pointlist)); Double yobtainvariance = obtainvariance (Createylist (pointlist)); Determine the split dimension based on variance Enumpisiontype pisiontype = sortlistbyxoryvariances (xobtainvariance, yobtainvariance, ref pointlist); Get the median point Medianpoint = Obtainmedian (pointlist); int medianindex = POINTLIST.COUNT/2; Build node kdtreenode treeNode = new Kdtreenode () { pisionpoint = medianpoint, pisiontype = Pisiontype , leftchild = Createtreenode (Pointlist.take (Medianindex). ToList ()), rightchild = Createtreenode (Pointlist.skip (Medianindex + 1). ToList ()) }; return treeNode; } else { return null;} }
4. KD Tree Search method
The overall search process for Kd-tree first finds a recent leaf node based on a normal lookup. But this leaf node is not necessarily the closest point. Then the backtracking operation finds the nearest point.
4.1 kd Tree Search Logic Flow
For tree T built from point sets, and find point P. Do the following with the root node as a node T
If T is a leaf node. The nearest point n is the value of the split point of T, and jumps to the 5th step; if T is not a leaf node, proceed to step 3rd
Then the method of splitting the T is determined, if it is divided by x-axis, the x value of P is compared with the X value of the node's splitting point, and the other is compared with the y-coordinate.
If P's comparison value is less than the comparison value of T, T is specified as the left child node of T. Instead of specifying T as the right child node of T, perform the 2nd step
Define the retrieval point m, set M to n
Calculates the distance between M and P d1,n the distance from M to D2.
If D1 >= D2 and has a parent node, then the parent node of M is performed 5 steps as the value of M, and if there is no parent node, the true nearest point TN is obtained; If D1 < D2 indicates that n is not the nearest point, perform the 8th step
If n has a sibling node, then n = N's sibling node; n = n is the parent node if n does not have a sibling node. Delete the original n node. The value of M is set to the new N node, and the 6th step is performed.
4.2 Code Implementation
Public Dot Findnearest (point searchpoint) {//search for nearest points nearestpoint = Dfssearch (This.rootnode, Searchpoint) by lookup method; Take the backtracking return Backtrcaksearch (Searchpoint, nearestpoint);} Private Point Dfssearch (kdtreenode node,point Searchpoint,bool Pushstack = True) {if (Pushstack = True) {//Use stack record query Path, because the tree node does not record the reason for the parent node Backtrackstack.push (node); } if (Node.pisiontype = = enumpisiontype.x) {return dfsxsearch (node,searchpoint); } else {return Dfsysearch (node, searchpoint); }}private Point Searchpoint,point Nearestpoint) {//If the stack of the record path is empty, it means that it has been traced back to the root node, the closest to the found is the true nearest point if ( Backtrackstack.isempty ()) {return nearestpoint; } else {Kdtreenode Tracknode = Backtrackstack.pop (); The distance between the backtracking point and the nearest point-to-find point is calculated separately double backtrackdistance = Obtaindistanfromtwopoint (Searchpoint, tracknode.pisionpoint); Double nearestpointdistance = Obtaindistanfromtwopoint (Searchpoint, nearestpoint); if (Backtrackdistance < nearestpointdistance) {//Deep copy node is intended to avoid damage to tree kdtreenode Searchnode = new Kdtreenode () {pisionpoint = Tracknode.pisionpoin T, Pisiontype = tracknode.pisiontype, Leftchild = tracknode.leftchild, Rightchild = Tracknode.rightch ILD}; Nearestpoint = Dfsbacktrackingsearch (Searchnode, searchpoint); }//recursion to root node return Backtrcaksearch (Searchpoint, nearestpoint); }}