[译]K-D-B-tree(草稿,第一次翻译)

原文地址:https://en.wikipedia.org/wiki/K-D-B-tree

计算机科学中,KDB-tree(k-dimensional B-tree)是一个用于划分K维搜索空间的树形结构,KDB-tree的目的是提供平衡KD树的搜索效率,同时提供B树面向块的存储来优化外部内存的访问。

介绍

类似于KD树,KBD tree组织K维空间的点,有助于范围搜索和多维数据库查询等操作。KDB tree通过在某个维度元素的比较将空间划分为两个子空间。使用2-D-B-tree举例子,空间划分使用和KD树相同的方式:使用某个维度的一个点,其他值要么小于或者大于当前值,分别分到左边和右边的划分平面上。

不同于KD树的地方,每个半空间不是自己的节点。而是和B树类似,KDB-tree中的节点以页来存储,树存储一个指针,指向根页。

结构

KDB-tree包括两种类型的页:

  • 区域页面: (region, child)对的集合包含边界区域的描述,加上该区域指向子页面的指针。
  • 点页面:(point, location)对的集合。数据库方面,location可能指向数据库记录的索引,对于K维空间中的点,可以被看成该空间中的点坐标。

当向KDB树插入元素时,导致节点的规模超过它的最优规模,页面溢出。因为KDB-tree的目的是优化外部内存访问,例如硬盘访问,当节点的规模超过外部内存页大小,一个叶被认为是溢出。

通过插入和删除操作,KDB树保持一些属性:

  • 该图是一个多叉树,区域页面指向子页面,并且不能为空。点页面是叶子节点。
  • 像B树,对于所有查询,到达叶节点的路径长度是相同的。
  • 如果根节点是区域页面,区域的联合是整个搜索空间。
  • 当一个区域页面的(region, child)对的儿子也是一个区域页面,所有儿子区域的联合是该页面。
  • 和上面例子相反,如果儿子是一个点页面,儿子中所有点必须被该区域包含。

KDB-tree中的操作 

 查询操作

KDB-tree中的查询是所有轴上的区间范围搜索。去见的集合被叫做查询区域。在k空间中,查询区域被视为整个k维空间中的一些子空间的边界。查询可以分为三种:

  • 一些区间跨越整个空间,查询叫做部分匹配查询.
  • 一些局域是点,其他是区域,所有查询叫做部分匹配查询。
  • 局域是所有点,边界也只是点,叫做精确匹配查询。

   算法:

  1. 如果树的根是空,终止,否则让页是根。
  2. 如果页是点页,返回(region, child)对中在查询区域中的所有点。
  3. 否则,页面是区域页面,对所有和查询区域交叉的(region, child)对,设置页面为儿子,递归执行步骤2。

插入操作

当页溢出时,KDB-tree插入操作需要页面的分裂操作,首先定义分裂操作。

分裂操作

首先,一个区域页面沿某个平面被分裂成两个新的区域页面,左区域页面和右区域页面。这些页面充满旧区域的页面,旧区域页面被删除了。然后,对于原区域的(region, child),记住child是一个页和区域指定一个真实的边界区域:

  1. 如果区域完全位于左边分裂平面,添加(region, child)到左边平面。
  2. 如果区域完全位于右边分裂平面,添加(region, child)到右边平面。
  3. 否则:
    1. 递归通过分裂平面分裂儿子,导致new_left_pagenew_right_page。
    2. 通过分裂平面分裂区域,导致left_region和right_region。
    3. 添加(left_region, new_left_page)到左边页面,添加(right_region, new_right_page)到右边页面。

插入算法

使用分裂算法,插入一个新的(point, location)对被实现如下:

  1. 如果根页面是空,简单的让根页面成为一个新的点页面,包含(point, location).
  2. 如果一个点上的精确匹配查询来来找到点应该加入的页面,如果该点已经在该页存在,终止。
  3. 添加(point, location)到该页面,如果该页面溢出了,让页面表示那个页。
  4. 让旧页面等于新页面。选择一些元素和维度来定义分裂平面,产生两个页面,并且其中一个页面不要因为新点的加入而溢出。分裂平面导致两个新的页面:new_left_pagenew_right_page和两个新的区域left_region和right_region。
  5. 如果页面不是根页面,跳到步骤6。否则,页面边吃父页面,用(left_region, new_left_page)和(right_region, new_right_page)取代(region, old_page).如果页面溢出,重复步骤4,否则终止。
  6. 让left_region成为左边分裂平面的整个搜索空间,让right_reigon成为右边分裂平面的整个搜索空间,设置根页面包含left_region和right_region.

选择分裂平面和分裂元素是很重要的,因为我们想平衡两个分裂平面的点数量。在一些情况下,错误的选择会导致不满意的分裂结果。也可能导致某个页面不能被某个维度分割。

删除操作

如果对存储的使用没有最小数量的要求,KDB-tree的删除是一个非常简单的。使用一个精确匹配查询去找到(point, location)对,我们只是简单的移除记录。

重组算法

因为删除会导致一些页面仅包含非常少的数据,重组KDB-tree来满足最小数目的存储要求是必要的。重组算法被使用当一个页面包含非常少的数据时,如下:

  1. 让页面成为p的父页面,包含(region, P)
  2. 找到页面中的区域以至于区域是邻近的,区域的联合形成矩阵区域。这些区域被认为是可连接的。让R表示这些区域的集合。
  3. 组合集合R成为一个新的页面S,如果S过多的,重复分裂直到结果页面满足要求。
  4. 用结果页面来取代集合R。

相关工作

类似于KD-tree,更新KDB-tree可能会导致递归的分裂一些节点。这是非常没有效率的,能导致几乎空的叶节点。Lomet和Salzberg提出一个结构hB-Tree来提高KDB-tree的性能,该结构通过在插入一条根到页的路径来限制分裂。这被实现通过存储区域为矩形。

最近,Bkd-tree被提出提供更快速的查询,以及接近静态KDB-tree的100%空间使用率。代替维护一棵树和重新平衡,log2(N/M)的kdb-tree集合被维护定期重建。

 

posted @ 2016-01-01 13:45  skycore  阅读(2899)  评论(0编辑  收藏  举报