KD Tree

转载地址:http://www.cnblogs.com/slysky/archive/2011/11/08/2241247.html


KD Tree

Kd-树 其实是K-dimension tree的缩写,是对数据点在k维空间中划分的一种数据结构。其实,Kd-树是一种平衡二叉树。

举一示例:

假设有六个二维数据点 = {(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},数据点位于二维空间中。为了能有效的找到最近邻,Kd-树采用分而治之的思想,即将整个空间划分为几个小部分。六个二维数据点生成的Kd-树的图为:

2D 3D KD-tree

 对于拥有n个已知点的kD-Tree,其复杂度如下:

  1. 构建:O(log2n)
  2. 插入:O(log n)
  3. 删除:O(log n)
  4. 查询:O(n1-1/k+m) m---每次要搜索的最近点个数

一 Kd-树的构建

Kd-树是一个二叉树,每个节点表示的是一个空间范围。下表表示的是Kd-树中每个节点中主要包含的数据结构。Range域表示的是节点包含的空间范围。Node-data域就是数据集中的某一个n维数据点。分割超面是通过数据点Node-Data并垂直于轴split的平面,分割超面将整个空间分割成两个子空间。令split域的值为i,如果空间Range中某个数据点的第i维数据小于Node-Data[i],那么,它就属于该节点空间的左子空间,否则就属于右子空间。Left,Right域分别表示由左子空间和右子空间空的数据点构成的Kd-树。

 

域名

数据类型

描述

Node-Data

数据矢量

数据集中某个数据点,是n维矢量

Range

空间矢量

该节点所代表的空间范围

Split

整数

垂直于分割超面的方向轴序号

Left

Kd-tree

由位于该节点分割超面左子空间内所有数据点构成的Kd-树

Right

Kd-tree

由位于该节点分割超面左子空间内所有数据点构成的Kd-树

Parent

Kd-tree

父节点

构建Kd-树的伪码为:

算法:构建Kd-tree

输入:数据点集Data_Set,和其所在的空间。

输出:Kd,类型为Kd-tree

1 if data-set is null ,return 空的Kd-tree

2 调用节点生成程序

 (1)确定split域:对于所有描述子数据(特征矢量),统计他们在每个维度上的数据方差,挑选出方差中最大值,对应的维就是split域的值。数据方差大说明沿该坐标轴方向上数据点分散的比较开。这个方向上,进行数据分割可以获得最好的分辨率。

(2)确定Node-Data域,数据点集Data-Set按照第split维的值排序,位于正中间的那个数据点 被选为Node-Data,Data-Set` =Data-Set\Node-data

3 dataleft = {d 属于Data-Set` & d[:split]<=Node-data[:split]}

   Left-Range ={Range && dataleft}

  dataright = {d 属于Data-Set` & d[:split]>Node-data[:split]}

  Right-Range ={Range && dataright}

4 :left =由(dataleft,LeftRange)建立的Kd-tree

   设置:left的parent域(父节点)为Kd

   :right =由(dataright,RightRange)建立的Kd-tree

设置:right的parent域为kd。

如上例中,

(1)确定:split 域=x,6个数据点在x,y 维度上的数据方差为39,28.63.在x轴方向上的方差大,所以split域值为x。

(2)确定:Node-Data=(7,2),根据x维上的值将数据排序,6个数据的中值为7,所以node-data域为数据点(7,2)。这样该节点的分割超面就是通过(7,2)并垂直于:split=x轴的直线x=7.

(3)左子空间和右子空间,分割超面x=7将整个空间分为两部分。x<=7 为左子空间,包含节点(2,3),(5,4),(4,7),另一部分为右子空间。包含节点(9,6),(8,1)

这个构建过程是一个递归过程。重复上述过程,直至只包含一个节点。

### KDTree 数据结构实现及应用 #### 什么是KDTreeKDTree(K-Dimensional Tree,K维树)是一种用于多维空间中数据点的快速点查找的数据结构。它属于计算几何领域中的二叉树结构[^1]。 #### KDTree的优点 - **搜索效率高**:通过分割空间的方式减少不必要的比较操作。 - **自平衡特性**:即使在动态插入和删除的情况下,仍然能够维持较高的性能。 - **易于实现**:相较于其他复杂的多维索引结构,其算法逻辑较为简单[^2]。 #### KDTree的核心原理 KDTree基于二叉搜索树的思想构建,在每次分裂时选择一个维度作为当前层的划分依据,并将该维度上的中间值设为节点,从而形成左子树和右子树。这种分治策略使得后续查询可以迅速定位目标区域而无需遍历整个数据集[^4]。 #### Python实现示例 以下是利用Python实现的一个简单的KDTree构造过程: ```python import random class Node: def __init__(self, point=None, axis=None): self.point = point self.axis = axis self.left_child = None self.right_child = None def kdtree(points, depth=0): n = len(points) if n == 0: return None # 当前轴由深度决定 (假设二维情况) axis = depth % 2 # 对当前轴进行排序并取中位数 sorted_points = sorted(points, key=lambda point: point[axis]) median_index = n // 2 median_point = sorted_points[median_index] node = Node(median_point, axis) # 构建左右子树 node.left_child = kdtree(sorted_points[:median_index], depth + 1) node.right_child = kdtree(sorted_points[median_index + 1:], depth + 1) return node if __name__ == "__main__": points = [(random.randint(0, 10), random.randint(0, 10)) for _ in range(7)] root = kdtree(points) ``` 上述代码展示了如何创建一棵基本的KDTree。其中`kdtree()`函数递归地按照不同维度对输入点集合进行拆分直到叶子节点为止。 #### 应用场景 - **范围搜索**:给定一个多边形或者矩形边界,寻找落在这个区域内所有的点。 - **最近邻搜索**:找到离某个特定位置最近的那个样本点。 - **碰撞检测**:应用于游戏开发等领域来判断物体之间是否存在接触可能性。 - **地理信息系统(GIS)**:比如在外卖平台里用来管理各个餐馆的位置信息以便用户能方便快捷地获取附近可选店铺列表等服务功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值