高维数据存储 —— R 树

概览

为什么需要R树

R树基于B树分段查询的思想。如果说B树更多的是在一维空间下,那么R树则是可以工作在更高维的空间下。我们拿美团举例,假如说我们想要知道两公里范围内的可配送商家都有哪些?

那么如果我们拿B树存储,其对于美团的商家的经度需要建立一棵B树,而对于纬度一样也需要建立一颗B树。我们这里拿坐标表示,假设我们要寻找[5,5]~[8,8]这个范围的所有商家,寻找过程如下:

首先我们要要寻找经度在[5,8]范围的商家,得到结果 E、F、G、H
在这里插入图片描述

之后我们根据纬度B树得到结果:K、A、E、C
在这里插入图片描述

最终聚合两次查找的结果得到两公里内的商家为E

这只是二维的情况下,如果是多维,那么必然要经历多个这样的过程。所以应运而生了R树这种数据结构。

R树

1984年,加州大学伯克利分校的Guttman发表了一篇题为“R-trees: a dynamic index structure for spatial searching”的论文,向世人介绍了R树这种处理高维空间存储问题的数据结构。

一棵 R 树满足如下性质:

  • 1)除根结点之外,所有非根结点包含有 m 至 M 个记录索引(条目)。根结点的记录个数可以少于 m。通常 m=M/2。

  • 2)每一个非叶子结点的分支数和该节点内的条目数相同,一个条目对应一个分支。所有叶子结点都位于同一层,因此 R 树为平衡树。

  • 3)叶子结点的每一个条目表示一个点。

  • 4)非叶结点的每一个条目存放的数据结构为:(I,child−pointer)。child−pointer 是指向该条目对应孩子结点的指针。I 表示一个 n 维空间中的最小边界矩形(minimumboundingrectangle,即 MBR),I 覆盖了该条目对应子树中所有的矩形或点。

我们还是拿这个例子举例,看R树是如何解决这个问题的。首先我们给出每个商家的二维坐标:
在这里插入图片描述
这样之后我们就可以开始划分区域范围了,首先可以分为两个大的区域R12和R13 。其中R12的范围是:[0,5]~[10,16],R2的范围是:[7,0]~[16,7]。这样在R1的范围内就有A、B、C、D、E、F、G、H、I;在R2的范围内有K、M、N、T、Z
在这里插入图片描述
虽然看着上面的十分复杂,但是我们将其用R树的树形结构表示一下便如下:
在这里插入图片描述

这就是R树的非叶子节点结构图,而叶子节点就是具体代表商家的A、B、C
这样我们搜索[5,5]~[8,8]区域的时候就会去从根节点R12和R13开始比对,很明显其是在R12[0,5]~[10,16]这个范围的。之后我们再次判断其是在R10[0,4]~[6,9]这个范围,之后不断迭代缩小范围最终查找到区域R5,这个时候读取区域R5范围内的节点,得到 E 这个答案。

这就是使用R树来解决这个问题,其比B树大大减少了搜寻的这个过程。对于更高维的问题则可以建造更高维的数据坐标系。

R树操作详解

R树构建

首先还是刚刚图,我们把每两个点之间采用MBR框起来,这里尽量的最小化每个 MBR 矩形,这样查询的时候发生的相交情况会越少,查询的分支就越少,查询效率越高。

我们这里采用两两划分一组,同时划分最近的两个点为一个叶子节点
在这里插入图片描述
这里,我们其实构建的就是叶子节点。其用C++代码就可以表示为如下的结构:

struct Element
{
	int x;
	int y;
};

struct LevelNode
{
	int area_x_begin;
	int area_x_end;

	int area_y_begin;
	int area_y_end;
	
	Element* elem1;
	Element* elem2;
}:

之后我们将这些叶子节点划分至非叶子节点之中,划分规则还是采用两两划分一组,同时划分最近的两个点为一个叶子节点。迭代这个过程最终形成如下图:
在这里插入图片描述
非叶子节点用C++代码表示就如下:

struct NotLevelNode
{
	int area_x_begin;
	int area_x_end;

	int area_y_begin;
	int area_y_end;
	
	LevelNode* level_node;
}:

KNN查询

刚刚我们介绍的是范围查询,现在来介绍一下KNN查询。假设我们有一个点X,我们要查询距离其最近的一个点:
在这里插入图片描述

首先,我们计算这个点到根节点R12和R13哪个近一些:

mindest(X,R12) = 2;
mindest(X,R13) = 5;

因为我们这里距离R12比较近,所以来到R12的child Tree:
在这里插入图片描述
这个时候我们再次计算X和R9、R10的距离:

mindest(X,R9) = 6;
mindest(X,R10) = 2;

这里最近的是R3,所以我们接着计算R12 的child Tree:
在这里插入图片描述
这个时候距离R10区域的点比较近,我们继续计算和R2以及R5区域的距离:

mindest(X,R2) = 3;
mindest(X,R5) =8;

这个时候距离R5区域更近,由于R5没有child Tree了,我们就可以读取R5区域的点,之后和这个要查找的点计算就可以。这个例子的计算结果就是 L 点。

参考文献

R树数据结构

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shenmingik

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值