编写二维Kd树(含比较器,Java语言描述)

关于Kd树啊,可能很多人没听说过。

Kd树是 K-dimension tree 的缩写,是对数据点在 K维空间(如二维(x,y),三维(x,y,z),K维(x,y,z, …))中划分的一种高维索引树形数据结构Kd树是一种空间划分树,说白了,就是把整个空间划分为特定的几个部分,然后在特定空间的部分内进行相关搜索操作。

Kd树从BST(Binary search tree)发展而来,在划分好的特定空间的部分内进行相关搜索操作。Kd树也是一种平衡二叉树

Kd树主要应用于多维空间关键数据的搜索,常用于大规模高维数据密集的查找比对的使用场景中,主要是最近邻查找(Nearest Neighbor)以及近似最近邻查找(Approximate Nearest Neighbor)。在计算机视觉(CV)中主要是图像检索和识别中的高维特征向量的查找和比对(本段文字参考自下面的这篇文章)

感兴趣的可以看这篇讲解

这里我们简单地实现一个二维划分的Kd树,二维的呦~。

二维Kd树实现代码

/**
 * Quick illustration of a two-dimensional tree.
 */
public class KdTree<T extends Comparable<? super T>> {

    private static class KdNode<T> {
        T[]     data;
        KdNode<T> left;
        KdNode<T> right;

        @SuppressWarnings("unchecked")
        KdNode(T[] item) {
            data = (T[]) new Comparable[2];
            data[0] = item[0];
            data[1] = item[1];
            left = right = null;
        }
    }

    private KdNode<T> root;

    public KdTree() {
        root = null;
    }

    public void insert(T[] x) {
        root = insert(x, root, 0);
    }

    private KdNode<T> insert(T[] x, KdNode<T> t, int level) {
        if(t == null) {
            t = new KdNode<>(x);
        } else if( x[level].compareTo(t.data[level] ) < 0) {
            t.left = insert(x, t.left, 1 - level);
        } else {
            t.right = insert(x, t.right, 1 - level);
        }
        return t;
    }

    /**
     * Print items satisfying
     * low[0] <= x[0] <= high[0] and
     * low[1] <= x[1] <= high[1].
     */
    public void printRange(T[] low, T[] high) {
        printRange(low, high, root, 0);
    }

    private void printRange(T[] low, T[] high, KdNode<T> t, int level) {
        if(t != null) {
            if(low[0].compareTo(t.data[0]) <= 0 && low[1].compareTo(t.data[1] ) <= 0 &&
                       high[0].compareTo(t.data[0]) >= 0 && high[1].compareTo(t.data[1]) >= 0) {
                System.out.println("(" + t.data[ 0 ] + "," + t.data[ 1 ] + ")");
            }
            if(low[level].compareTo(t.data[level]) <= 0) {
                printRange(low, high, t.left, 1-level);
            }
            if(high[level].compareTo(t.data[level]) >= 0) {
                printRange(low, high, t.right, 1-level);
            }
        }
    }

}

测试

public class KdTreeTest {
    public static void main(String [] args) {
        KdTree<Integer> t = new KdTree<>();
        System.out.println("Starting program");
        for(int i = 300; i < 370; i++) {
            Integer [] it = new Integer[2];
            it[0] = i;
            it[1] = 2500-i;
            t.insert(it);
        }
        Integer [] low = {70, 2186};
        Integer [] high = {1200, 2200};
        t.printRange(low, high);
    }
}

测试结果:

Starting program
(300,2200)
(301,2199)
(302,2198)
(303,2197)
(304,2196)
(305,2195)
(306,2194)
(307,2193)
(308,2192)
(309,2191)
(310,2190)
(311,2189)
(312,2188)
(313,2187)
(314,2186)
发布了570 篇原创文章 · 获赞 1179 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/weixin_43896318/article/details/104467560