Java 2dkd树与最近邻搜索
我目前正在按照此处描述的算法实现KD树和最近邻搜索: 我遇到了两种实现KD树的不同方法,一种是将点存储在内部节点中,另一种是仅将点存储在叶节点中。因为我有一个非常简单的用例,所以我只需要构建一次树,它不需要修改,我选择的是纯叶方法,因为它看起来更容易实现。我已经成功地实现了一切,树总是成功地构建,在大多数情况下,最近邻搜索返回正确的值。但是,我有一些问题,对于一些数据集和搜索点,算法返回的值不正确。考虑点:Java 2dkd树与最近邻搜索,java,algorithm,search,nearest-neighbor,kdtree,Java,Algorithm,Search,Nearest Neighbor,Kdtree,我目前正在按照此处描述的算法实现KD树和最近邻搜索: 我遇到了两种实现KD树的不同方法,一种是将点存储在内部节点中,另一种是仅将点存储在叶节点中。因为我有一个非常简单的用例,所以我只需要构建一次树,它不需要修改,我选择的是纯叶方法,因为它看起来更容易实现。我已经成功地实现了一切,树总是成功地构建,在大多数情况下,最近邻搜索返回正确的值。但是,我有一些问题,对于一些数据集和搜索点,算法返回的值不正确。考虑点: [[6, 1], [5, 5], [9, 6], [3, 81], [4, 9], [4
[[6, 1], [5, 5], [9, 6], [3, 81], [4, 9], [4, 0], [7, 9], [2, 9], [6, 74]]
它构造了一棵树,看起来像这样。请原谅我的图表设计不好:
其中,方形叶节点是包含点的节点,圆形节点包含用于在该深度拆分列表的中值。在该数据集上调用“我的最近邻搜索”并查找[6,74]的最近邻时,算法返回[7,9]。虽然这正确地遵循了算法,但实际上它不是最接近[6,74]的点。最近的点实际上是[3,81],距离为7.6,[7,9]距离为65
以下是绘制的点,用于可视化,红色点是我试图找到的最近邻点:
如果有帮助,我的搜索方法如下:
private LeafNode search(int depth, Point point, KDNode node) {
if(node instanceof LeafNode)
return (LeafNode)node;
else {
MedianNode medianNode = (MedianNode) node;
double meanValue = medianNode.getValue();
double comparisonValue = 0;
if(valueEven(depth)) {
comparisonValue = point.getX();
}
else {
comparisonValue = point.getY();
}
KDNode nextNode;
if(comparisonValue < meanValue) {
if (node.getLeft() != null)
nextNode = node.getLeft();
else
nextNode = node.getRight();
}
else {
if (node.getRight() != null)
nextNode = node.getRight();
else
nextNode = node.getLeft();
}
return search(depth + 1, point, nextNode);
}
}
因此,我的问题是:
这是KD树中最近邻搜索的预期结果,还是我应该得到距离我正在搜索的点最近的点,因为这是我使用该树的唯一原因
这是否只是KD树的一个问题,我是否应该将其更改为在内部节点中存储点以解决此问题
KD树的正确实现总是能找到最近的点。点是否仅存储在叶子中并不重要。但是,您的搜索方法不正确。下面是它的外观:
bestDistance = INF
def getClosest(node, point)
if node is null
return
// I will assume that this node splits points
// by their x coordinate for the sake of brevity.
if node is a leaf
// updateAnswer updates bestDistance value
// and keeps track of the closest point to the given one.
updateAnswer(node.point, point)
else
middleX = node.median
if point.x < middleX
getClosest(node.left, point)
if node.right.minX - point.x < bestDistance
getClosest(node.right, point)
else
getClosest(node.right, point)
if point.x - node.left.maxX < bestDistance
getClosest(node.left, point)
在ldots.org上给出的解释与谷歌搜索KD树的其他顶级搜索结果完全错误
请参阅以获得正确的实现。不确定此答案是否仍然相关,但无论如何,我敢建议以下kd树实现: 该实现非常简单,如果您决定在实践中理清这些事情是如何工作的,那么它将非常有用
关于树的构建方式,使用了迭代方法,因此它的大小受内存而不是堆栈大小的限制。啊,我明白了!谢谢,我的问题中链接的文章中的psuedo代码似乎有点误导。它没有考虑到NN可能不存在于最初递归到的子树中的事实,需要在递归备份时检查其他子树。