Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 2dkd树与最近邻搜索_Java_Algorithm_Search_Nearest Neighbor_Kdtree - Fatal编程技术网

Java 2dkd树与最近邻搜索

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

我目前正在按照此处描述的算法实现KD树和最近邻搜索:

我遇到了两种实现KD树的不同方法,一种是将点存储在内部节点中,另一种是仅将点存储在叶节点中。因为我有一个非常简单的用例,所以我只需要构建一次树,它不需要修改,我选择的是纯叶方法,因为它看起来更容易实现。我已经成功地实现了一切,树总是成功地构建,在大多数情况下,最近邻搜索返回正确的值。但是,我有一些问题,对于一些数据集和搜索点,算法返回的值不正确。考虑点:

[[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可能不存在于最初递归到的子树中的事实,需要在递归备份时检查其他子树。