k-d tree算法原理

k-d tree算法原理

k-d树( k-维树的缩写)是在k维欧几里德空间组织点的数据结构。k-d树可以使用在多种应用场合,如多维键值搜索(例:范围搜寻及最邻近搜索)。k-d树是空间二分树(Binary space partitioning )的一种特殊情况。—— *

从二叉查找树(Binary Search Tree)开始

二叉查找树(Binary Search Tree,BST),是具有如下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉排序树;

下图为一棵典型的二叉查找树:

k-d tree算法原理

根节点对应的就是2,左子树(比2小)都在2的左边,右子树(比2大)都在2的右边,整个一维空间就被根节点分割成了两个部分,当要查找结点0的时候,由于是在2的左边,所以可以放心的只搜索左子树的部分。整个搜索的过程可以看成不断分割搜索区间的过程,直到找到目标节点。

将一个1维数据集用一棵BST树存储后,当我们想要查询某个数据是否位于该数据集合中时,只需要将查询数据与结点值进行比较然后选择对应的子树继续往下查找即可,查找的平均时间复杂度为:O(logN),最坏的情况下是O(N)。

构造k-d tree

对于K维空间的数据集,我们可以类比1维空间,关键在于确定根节点,利用根节点划分左子树和右子树。通过根节点,我们想让数据尽可能的均匀分散在根节点两侧。对于一维数据,取中位数即可,但是二维空间,选择哪一个维度呢?

下图中,左侧以X轴中位数分割,每次右侧以Y轴中位数分割。由于数据在X轴相对分散,在X轴相对稠密,所以,以X轴中中位数作为划分,更容易将数据分成两部分。也就是说,对于多维数据集,取更加分散的维度,利用该维度的中位数,划分效果更加好,而方差就是描述数据分散和稠密的数学语言,方差越大,数据越分散。

k-d tree算法原理k-d tree算法原理

算法描述

  1. 在K维数据集合中选择具有最大方差的维度k,然后在该维度上选择中值m为pivot对该数据集合进行划分,得到两个子集合;同时创建一个中间结点(k,m) :
  2. 对两个子集合重复步骤1的过程,直至所有子集合都不能再划分为止;如果某个子集合不能再划分时,则将该子集合中的数据保存到叶子结点(leaf node)。

举个例子

下面,我们以二维数据集{(2,3), (5,4), (9,6), (4,7), (8,1), (7,2)}为例,说明k-d tree的构造过程。该数据集对应的二维空间分布为下图:

k-d tree算法原理
  • 计算X轴和Y轴方向的方差,分别为2.4,2.1,以X轴方向划分数据,根节点为<1,5>表示第一维,中位数为5:
k-d tree算法原理k-d tree算法原理
  • 在左子树中,数据集为{(2,3),(4,7) (5,4)},X轴和Y轴方向的方差分别为1.2,1.6,以Y轴方向划分数据集,根节点为<2,4>表示第二维,中位数维4;在右子树中,数据集为{(7,2),(8,1) (9,6)},X轴和Y轴方向的方差分别为0.8,2.1,以Y轴方向划分数据集,根节点为<2,2>表示第二维,中位数维2。
k-d tree算法原理

最终的k-d tree 如下图所示,其中圆圈代表了中间结点(k, m),而矩形代表了叶子结点:

k-d tree算法原理

最近邻查找

算法描述

(1)将查询数据Q从根结点开始,按照Q与各个结点的比较结果向下访问Kd-Tree,直至达到叶子结点。

其中Q与结点的比较指的是将Q对应于结点中的k维度上的值与m进行比较,若Q(k) < m,则访问左子树,否则访问右子树。达到叶子结点时,计算Q与叶子结点上保存的数据之间的距离,记录下最小距离对应的数据点,记为当前“最近邻点”Pcur和最小距离Dcur。

(2)进行回溯(Backtracking)操作,该操作是为了找到离Q更近的“最近邻点”。即判断未被访问过的分支里是否还有离Q更近的点,它们之间的距离小于Dcur。

如果Q与其父结点下的未被访问过的分支之间的距离小于Dcur,则认为该分支中存在离P更近的数据,进入该结点,进行(1)步骤一样的查找过程,如果找到更近的数据点,则更新为当前的“最近邻点”Pcur,并更新Dcur。

如果Q与其父结点下的未被访问过的分支之间的距离大于Dcur,则说明该分支内不存在与Q更近的点。

回溯的判断过程是从下往上进行的,直到回溯到根结点时已经不存在与P更近的分支为止。

举个例子

查询数据Q(8,3)的最近邻节点:

  • 按照根节点(1,5)比较,Q的第1维比根节点大,属于右子树;按照右子树的根节点(2,5)比较,Q第2维比根节点大,属于右子树,进入叶子节点,计算叶子节点中最近的距离Dcur=10
  • 回溯,Q到分界线的距离小于Dcur,存在更近邻的节点,只需,进入左子树,更新Dcur=2
k-d tree算法原理
  • 回溯,Q到分界线的距离大于Dcur,结束。
k-d tree算法原理