数学-kd树

本文深入解析kd树的二叉树结构及其构建过程,通过实例演示如何沿不同维度分割空间,形成高效的kNN搜索基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://zhuanlan.zhihu.com/p/23966698

导语:在上一篇《kd 树算法之思路篇》中,我们介绍了如何用二叉树格式记录空间内的距离,并以其为依据进行高效的索引。在本篇文章中,我们将详细介绍 kd 树的构造以及 kd 树上的 kNN 算法。

作者:肖睿
编辑:宏观经济算命师

本文由JoinQuant量化课堂推出,本文的难度属于进阶(下),深度为 level-1

 

kd 树的结构

kd树是一个二叉树结构,它的每一个节点记载了【特征坐标,切分轴,指向左枝的指针,指向右枝的指针】。

其中,特征坐标是线性空间R^n中的一个点(x_1,x_2,...,x_n)

切分轴由一个整数r表示,这里1 \le r \le n,是我们在 n 维空间中沿第 r 维进行一次分割。

节点的左枝和右枝分别都是 kd 树,并且满足:如果 y 是左枝的一个特征坐标,那么y_r \le x_r并且如果 z 是右枝的一个特征坐标,那么z_r \ge x_r

给定一个数据样本集 S \subseteq R^n和切分轴 r , 以下递归算法将构建一个基于该数据集的 kd 树,每一次循环制作一个节点:

−− 如果 |S|=1,记录 S 中唯一的一个点为当前节点的特征数据,并且不设左枝和右枝。(|S| 指集合 S 中元素的数量)
−− 如果 |S|>1
∙∙ 将 S 内所有点按照第 r 个坐标的大小进行排序;
∙∙ 选出该排列后的中位元素(如果一共有偶数个元素,则选择中位左边或右边的元素,左或右并无影响),作为当前节点的特征坐标,并且记录切分轴 r;
∙∙ 将 S_L 设为在 S 中所有排列在中位元素之前的元素; S_R 设为在 S 中所有排列在中位元素后的元素;
∙∙ 当前节点的左枝设为以 S_L 为数据集并且 r 为切分轴制作出的 kd 树;当前节点的右枝设为以 S_R 为数据集并且 r 为切分轴制作出的 kd 树。再设 r\leftarrow(r+1)\ mod\ n。(这里,我们想轮流沿着每一个维度进行分割;mod\ n 是因为一共有 n 个维度,在沿着最后一个维度进行分割之后再重新回到第一个维度。)

构造 kd 树的例子

上面抽象的定义和算法确实是很不好理解,举一个例子会清楚很多。首先随机在 \mathbb{R}^2 中随机生成 13 个点作为我们的数据集。起始的切分轴r=0;这里 r=0 对应 xx 轴,而r=1 对应 y 轴。

首先先沿 x 坐标进行切分,我们选出 x 坐标的中位点,获取最根部节点的坐标

 

并且按照该点的x坐标将空间进行切分,所有 x 坐标小于 6.27 的数据用于构建左枝,x坐标大于 6.27 的点用于构建右枝。

 

在下一步中 r=0+1=1\ mod\ 2 对应 y 轴,左右两边再按照 y 轴的排序进行切分,中位点记载于左右枝的节点。得到下面的树,左边的 x 是指这该层的节点都是沿 x 轴进行分割的。

 

空间的切分如下

 

下一步中 r≡1+1≡0 mod 2,对应 x 轴,所以下面再按照 x 坐标进行排序和切分,有

最后每一部分都只剩一个点,将他们记在最底部的节点中。因为不再有未被记录的点,所以不再进行切分。

就此完成了 kd 树的构造。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值