多维检索树KD-Tree

K维检索树类似于二叉检索树,不同的是,它能同时提供多维度属性的检索。K维(从0开始计维数)检索树的定义: K维检索树是一个n层的二叉树(根节点为第0层,依次往下为第1,2..n-1层),对于树中第n层的每个节点,其左子树所有节点的第n%k维属性小于或等于该节点的第n%k维属性;其右子树所有节点的第n%k维属性都大于或等于该节点的第n%k维属性。通俗的讲,就是将整个树的层数循环标记0k-1,在第0层比较第0为属性,在第1层比较第1层属性,依此类推。

 

假设A-G代表二维空间的点(x,y二维坐标标示),则依次插入A-G节点到树中会构成如下所示的树。


20196318_1322026991888c.jpg 

 

插入A

树为空,A作为根节点

插入B

A比较第0维属性,进入左子树,左子树为空,直接插入

插入C

A比较第0维属性,进入右子树,右子树为空,直接插入

插入D

A比较第0维属性,进入左子树,与B比较第1维属性,进入左子树

插入E

A比较第0维属性,进入左子树,与B比较第1维属性,进入右子树

插入F

A比较第0维属性,进入右子树,与C比较第1维属性,进入右子树

插入G

A比较第0维属性,进入左子树,与B比较第1维属性,进入左子树,D比较第0维属性,进入左子树

 

算法时间复杂度:

查找:从根节点逐层比较,直到遇到目标或者子树为空,时间复杂度为O(logN)

插入:从根节点逐层比较,按照定义的规则直到遇到叶子节点,时间复杂度为O(logN)

删除:对于叶子节点,或只有单分支子树的节点,直接删除,否则找到右子树的最左节点或左子树的最右节点,替换掉被删节点,算法复杂度O(logN)

优化:将树优化为平衡树,将树的节点导出至vector中,并清空树,将vector集合按第一维属性,分成两堆,左边比中间元素小,右边比中间元素大(nth-element),将中间元素插入到树中,递归将左右两堆的元素插入到左子树、右子树(比较时根据层数比较对应的维度值)。优化的时间复杂度为ONlogN)。

区间查找:从根节点起,检查根节点是否符合条件,如果符合加入至结果集中;如果左子树跟目标区间有交集,递归查找左子树;如果右子树跟目标区间有交集,查找右子树。(设定一个动态区间,初始时与目标区间相同,进入左子树,则要更新动态区间对应维度的上限;若进入右子树,则要更新动态区间对应维度的上限;通过判断动态和目标区间是否有交集可以看出需要进入左右子树,从而减少查找空间)。

 

更详细的了解参考论文:Multidimensional Binary Search Trees Used for Associative Searching

 

libkdtree++是一个C++实现的kdtree lib,提供了inserteraseoptimisefind_exact

find_within_rangefind_nearest等接口。

find_with_range(val, range, OutputIterator)不能满足需求,因只能指定每维属性在

val[k] – rangeval[k] + range的范围内。因为需要支持任意区间查找,而kdtree++没有提供

需要的接口,我在kdtree的实现中增加了find_within_range(vmin, vmax, OutputIterator)接口,

同时需要给Region添加一个构造函数。

 

 

 

转载于:https://www.cnblogs.com/yunnotes/archive/2013/04/19/3032333.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值