CGAL的D维范围树和线段树

        范围树和线段树是两种数据结构,用于高效地处理和查询数据。

        范围树(Range Tree)是一种二叉树,它通过递归地将每个节点分割成两个子节点来存储一个点集。每个节点表示一个范围,并且存储该范围内所有点的最小和最大值。范围树主要用于查询和更新操作,例如找到落在某个范围内的所有点。

        线段树(Segment Tree)也是一种二叉树,但它主要用于存储有序的序列。每个节点表示一个线段,存储该线段上的最小和最大值。线段树主要用于查询和更新操作,例如找到某个范围内的最小值或最大值。

        这两种数据结构都是用于处理有序数据的强大工具,但在使用时需要小心地处理节点之间的关系和数据更新。 

1、定义

        本节介绍d维范围和分段树。一维范围树是一维点数据上的二叉搜索树。在这里,我们称所有具有严格顺序的一维数据类型(如整数和双精度数)为点数据。d维点数据是一维点数据的d元组。

        一维分段树也是二叉搜索树,但输入数据是一维区间数据。一维区间数据是一对(即二元组)(a,b),其中a和b是相同类型的一维点数据,并且a<b。对(a,b)表示半开区间[a,b)。类似地,d维区间由一维区间的d元组表示。

        d维树的输入数据类型是一个容器类,由d维点数据类型、区间数据类型或两者的混合组成,还可以选择一个值类型,可用于存储任意数据。例如,d维多边形的d维边界框可以定义d维段树的区间数据,多边形本身可以作为其值存储。输入数据项是输入数据类型的实例。

        范围树和分段树类是完全通用的,因为它们可以用来定义多层树。维度(层数)为d的多层树是第d层的简单树,而树的第k层(1<=k<=d-1)定义了一个树,其中每个(内部)顶点包含一个维度为d-k+1的多层树。嵌套在k维树(T)中的k-1维树称为子层树(T)。例如,d维树可以是第一层的范围树,根据d维数据项的第一维构建。在每个子树中的所有数据项上,根据数据项的第二维,构建一个(d-1)维树,无论是范围树还是分段树。等等。

        区间树和分段树中的数字以图形方式说明了子层树的方法。

        创建树后,不允许进一步插入或删除数据项。树类既不依赖于数据类型,也不依赖于数据项的具体物理表示。例如,让多层树成为分段树,每个顶点定义一个范围树。我们可以选择由双精度类型区间和整数类型点数据组成的数据项。作为值类型,我们可以选择字符串。

        为了实现这种通用性,我们必须定义每个维度的树是什么样子的,以及输入数据是如何组织的。对于维度 k,1 < k < 4,CGAL 提供了现成的范围树和分段树,可以存储 k 维的键(区间)。 示例说明了这些类的使用,如类范围树在类数据上的示例和类分段树在类数据上的示例。这些类的功能描述以及更高维度的树和混合多层树的定义在参考手册中给出。

        在接下来的两节中,我们将简要介绍这里实现的区间树和分段树的版本,并给出一些示例。

2、软件设计

        为了能够定义多层树,我们首先设计了范围树和分段树,使其具有一个模板参数来定义子层树的类型。有了这个子层树类型信息,子层就可以创建了。这种方法导致了嵌套模板参数,因为子层树可以再次具有一个模板参数来定义子层。因此,内部类和函数的标识符变得比编译器相关的限制还要长。这种情况在d=2时就已经发生了。

        因此,我们选择了另一种面向对象的设计。我们定义了一个名为Tree_base的纯虚基类,并从中派生了Range_tree_d和Segment_tree_d类。

        这些类的构造函数期望一个名为sublayer_prototype的参数,其类型为Tree_base。由于Range_tree_d和Segment_tree_d类都从Tree_base类派生,因此可以使用Range_tree_d或Segment_tree_d类的实例作为构造函数参数。这个参数定义了树的子层树。

        例如,您可以使用一个Segment_tree_d类的实例作为构造函数参数来构造一个Range_tree_d。然后,您就定义了一个具有分段树作为子层树的范围树。由于Range_tree_d和Segment_tree_d类在构造函数中都期望一个子层树,我们不得不从Tree_base类派生出一个名为Tree_anchor的第三个类,它不需要构造函数参数。这个类的实例被用作Range_tree_d或Segment_tree_d类的构造函数参数,以停止递归。

        所有类都提供 clone() 函数,该函数返回相同树类型的实例(副本)。在构造树时调用 sublayer_prototype 的 clone() 函数。如果子层树再次具有子层,则它也具有一个 sublayer_prototype,该 sublayer_prototype 也被克隆,依此类推。因此,调用 clone() 函数会生成一个子层树,该子层树具有关于其子层树的完整知识。

        树允许对键进行窗口查询、封闭查询和反向范围查询。显然,反向范围查询只在段树中才有意义。为了执行反向范围查询,需要先对 ϵ宽度必须执行。我们不希望为这种查询提供额外功能,因为反向范围查询是范围查询的特例。此外,在段树类中提供反向范围查询意味着在范围树类中也提供此功能,并在特征类中添加一个额外的项目来访问反向范围查询点。

        树由三个参数模板化:数据、窗口和特征。类型数据定义了输入数据类型,类型窗口定义了查询窗口类型。树使用一组定义良好的函数来访问数据。这些函数必须由类特征提供。

        该设计部分遵循[2]中的原型设计模式。与我们的第一种使用模板的方法相比,我们想指出以下几点:在这种方法中,子层类型是在运行时使用面向对象编程定义的,而在使用模板的方法中,子层类型是在编译时定义的。

        在这种面向对象的设计中使用虚成员函数所导致的运行时开销是可以忽略不计的,因为所有虚函数都是非平凡的。

        设计理念如下图所示。

 范围和分段树数据结构的设计。符号三角形表示下层阶级是从上层阶级派生而来的。

        例如,为了定义一个二维多层树,它由第一维的范围树和第二维的分段树组成,我们进行如下操作:我们构造一个类型为tree_ancher的对象,该对象停止递归。然后,我们构造一个类型为Segment_tree_d的对象,该对象得到类型为tree_ancher的对象作为原型参数。之后,我们定义了一个类型为Range_tree_d的对象,该对象是用类型为Segment_tree_d的对象作为原型参数构建的。下面的代码说明了二维多层树的构造。

int main(){Tree_Anchor *anchor=new Tree_Anchor;Segment_Tree_d *segment_tree = new Segment_Tree_d(*anchor);Range_Tree_d *range_segment_tree = new Range_Tree_d(*segment_tree);// let data_items be a list of Data itemsrange_segment_tree->make_tree(data_items.begin(),data_items.end());
}

        这里,类Tree_Aanchor、Segment_Tree_d和Range_Tree_d由typedefs定义: 

typedef Tree_anchor<Data,Window> Tree_Anchor;
typedef Segment_tree_d<Data,Window,Interval_traits> Segment_Tree_d;
typedef Range_tree_d<Data,Window,Point_traits> Range_Tree_d;

        类 Tree_base 和类 Tree_anchor 获得两个模板参数:一个定义了存储在树中的数据类型的类 Data,以及一个定义了查询范围类型的类 Window。派生类 Range_tree_d 和 Segment_tree_d 额外获得一个名为 Tree_traits 的参数,该参数定义了 Data 和树之间的接口。让 Data 类型是一个 d 维元组,在每个维度上可以是点数据或区间数据。然后,类 Tree_traits 提供对该树层的点(或区间)数据的访问器和一个比较函数。让我们回忆一下二维树的例子,它是一个第一维是区间树,第二维是段树的二维树。然后,类 Segment_tree_d 的 Tree_traits 类模板参数定义了 Data 的区间数据的访问器,而类 Range_tree_d 的 Tree_traits 类模板参数定义了 Data 的点数据的访问器。这些类的示例实现如下所示。

struct Data{int min,max; // interval datadouble point; // point data
};
struct Window{int min,max;double min_point, max_point;
};
class Point_traits{
public:typedef double Key;Key get_key(Data& d){return d.point;} // key accessoKey get_left(Window& w){return w.min_point;}Key get_right(Window& w){return w.max_point;}bool comp(Key& key1, Key& key2){return (key1 < key2);}
};
class Interval_traits{
public:typedef int Key;Key get_left(Data& d){return d.min;}Key get_right(Data& d){return d.max;}Key get_left_win(Window& w){return w.min;}Key get_right_win(Window& w){return w.max;}static bool comp(Key& key1, Key& key2){return (key1 < key2);}
};

3、创建任意多层树

        现在让我们仔细看看多层树是如何构建的。在创建d维树的情况下,我们处理一系列任意数据项,其中每个项目定义一个d维区间、点或其他对象。树是由该结构的迭代器构造的。在第i层,树是相对于定义第i维的数据槽构建的。因此,我们需要定义哪个数据槽对应哪个维度。此外,我们希望我们的树能够处理任意数据项。这需要在算法和数据项之间使用适配器。这是通过使用特征类解决的,特征类以函数对象的形式实现。这些类提供对数据项的指定数据槽的访问函数。然后通过为每一层定义一个特征类,为每一层分别定义d维树。

4、范围树

        一维范围树是一维点数据的二叉搜索树。树的点数据存储在叶子中。每个内部顶点存储其左子树中的最高条目。这里实现的范围树版本是静态的,这意味着在构建树之后,不能插入或删除元素。d维范围树是根据d维点数据的第一个维度构建的二叉叶搜索树,其中每个顶点包含一个关于第二个维度的子树(子层树)中的点的(d-1)-维搜索树。

        d维范围树可用于确定给定d维区间内的所有d维点(窗口查询)。

        下面的图片显示了一个二维和d维范围树。

二维和d维范围树。 

        二维树是第一维上的二叉搜索树。 顶点v的每个子层树是第二维上的二叉搜索树。 v的子层树中的数据项是v子树中的所有数据项。

        对于d维范围树,图中显示了树中每一层的一个子层树。

        该树可以在 O(nlogd−1n)时间内建立,需要 O(nlogd−1n)空间。位于 d 维查询区间内的 d 维点可以在 O(logdn+k)时间内报告,其中 n 是点的总数,k 是报告的点的数量。

5、线段树

        线段树是给定坐标集的静态二叉搜索树。坐标集由输入数据区间的端点定义。任何两个相邻坐标构成一个基本区间。每个叶子对应一个基本区间。内部顶点对应于该顶点子树区间的并集。每个顶点或叶子v包含一个子层类型(或列表,如果是一维的),其中包含所有区间I,使得I包含顶点v的区间,但不包含v的父顶点的区间。

        d维的段树可以用来解决以下问题:

        确定包含d维点的所有d维区间。这种查询类型称为反向范围查询。

        确定包围给定d维区间(包围查询)的所有d维区间。

        确定部分重叠或包含在给定d维区间中的所有d维区间(窗口查询)。

        下面显示了一维分段树的一个示例和二维分段树的一个示例。

 一维和二维分段树

        对于一维分段树,分段和相应的基本区间显示在树下方。从节点指向其子集的弧线。

        对于二维分段树,我们看到树的第一层是根据第一维的基本区间构建的。每个顶点v的子层树都是根据v的所有数据项的第二维构建的分段树。

        树可以在O(nlogdn)时间内建立,需要O(nlogdn)空间。d维段树中逆范围查询的处理时间为O(logdn+k)时间,其中n是区间总数,k是报告的区间数。

        二维分段树的一个可能应用如下。给定二维空间中的一组凸多边形(Polygon_2),我们想确定与给定矩形查询窗口相交的所有多边形。因此,我们定义了一个二维分段树,其中数据项的二维区间对应于多边形的边界框,值类型对应于多边形本身。分段树由所有数据项的序列创建,并执行窗口查询。最后对结果数据项的多边形进行独立交叉测试。

6、其他

        原型设计模式是一种创建型设计模式,它允许通过复制(或克隆)现有对象来创建新对象,而无需从头开始实例化对象。这种设计模式主要用于减少创建对象的成本和时间,同时提供了一种简洁的方式来创建相似或相同的对象。

        在原型设计模式中,通常会有一个原型对象作为模板,其他对象可以通过复制这个原型对象来创建。这种复制过程通常是通过实现一个克隆方法(如 clone())来完成的,该方法会创建一个与原型对象具有相同状态的新对象。

        2维线段树是即一维线段树中每个节点都是一维线段树,多维同理。线段树是二叉搜索树。

        一维范围树的示例。除叶子以外的每个节点都在其左子树中存储最大值。

        一组一维点上的范围树被视为这些点上的平衡二叉搜索树。存储在树中的点存储在树的叶子中;每个内部节点都存储其左侧子树中包含的最大值。 d维点集上的范围树是递归定义的多级二进制搜索树。数据结构的每个级别都被视为d维之一上的二进制搜索树。第一级是第一个d坐标上的二叉搜索树。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/580964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

静物摄影在UE5里运用几点记要

被摄体&#xff0c;相机与光源的关系&#xff0c;要增强立体感&#xff0c;摄像机与光源的位置关系要错开&#xff1b;b的立体感要更强 漫反射与点光源&#xff0c;UE5太阳光属于漫反射&#xff0c;整体比较柔和&#xff0c;但是阴影处比较黑&#xff1b;摄影棚会用反光板来增亮…

【模型】模型量化技术:动态范围、全整数和Float16量化

目录 一 动态范围量化 二 全整数量化 三 float16量化 通常&#xff0c;表示神经网络的数据类型是32位浮点数&#xff08;float32&#xff09;&#xff0c;这种数据类型可以提供高精度的计算&#xff0c;但是在计算资源和存储空间有限的设备上运行神经网络时&#xff0c;会带…

SpringBoot 异步编程浅谈

1. 需求背景 当我们需要提高系统的并发性能时&#xff0c;我们可以将耗时的操作异步执行&#xff0c;从而避免线程阻塞&#xff0c;提高系统的并发性能。例如&#xff0c;在处理大量的并发请求时&#xff0c;如果每个请求都是同步阻塞的方式处 理&#xff0c;系统的响应时间会…

Git使用教程 gittutorial

该教程对该文章的翻译&#xff1a;https://git-scm.com/docs/gittutorial 本文介绍怎用使用 Git 导入新的工程、修改文件及如何其他人同步开发。 首先&#xff0c; 可以使用以下指令获取文档帮助 git help log笔者注&#xff1a;不建议看这个文档&#xff0c;标准的语法介绍…

FreeRTOS的学习

1.创建函数和删除 动态创建为FreeRTOS分配的堆栈&#xff08;方便&#xff09;&#xff0c;而静态创建为人为分配空间。动态应用多任务中必须有while&#xff08;1&#xff09;否则只会执行一次任务中的延时要用 vTaskDelay(500); 延时期间执行其它任务 任务中的延时使…

postman进阶使用

前言 对于postman的基础其实很容易上手实现&#xff0c;也有很多教程。 对于小编我来说&#xff0c;也基本可以实现开发任务。 但是今年我们的高级测试&#xff0c;搞了一下postman&#xff0c;省去很多工作&#xff0c;让我感觉很有必要学一下 这篇文章是在 高级测试工程师ht…

01-Spring Security框架的认证和授权测试

Spring Security 介绍 认证功能与业务无关几乎是每个项目都要具备的功能,市面上有很多认证框架如Apache Shiro、CAS、Spring Security等 Spring Security是Spring家族的一份子且和Spring Cloud集成的很好&#xff0c;所以本项目采用Spring Security作为认证服务的技术框架 …

vue3(六)-基础入门之自定义组件与插槽、ref通信

一、全局组件 html: <div id"app"><mytemplace></mytemplace> </div>javascript: <script>const { createApp } Vueconst app createApp({})app.component(mytemplace, {template: <div><button>返回</button>…

canvas随机绘制100个五角星

canvas实例应用100 专栏提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。 canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重要的帮助。 文章目录 示例…

element-plus修改主题颜色

一、自定义scss文件 在src\css\styles\element目录下新建index.scss 代码如下 forward "element-plus/theme-chalk/src/common/var.scss" with ($colors: ("primary": ("base": #d61b1a,"color": #fff,),) );use "element-plus…

Java - 工厂设计模式

Java - 工厂设计模式 一. 简介二. 例子2.1 定义抽象类2.2 定义子类2.3 创建工厂2.4 测试 三. JDK中使用工厂模式的案例 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 工厂设计模式…

Day73力扣打卡

打卡记录 统计移除递增子数组的数目 II&#xff08;双指针&#xff09; 链接 class Solution:def incremovableSubarrayCount(self, a: List[int]) -> int:n len(a)i 0while i < n - 1 and a[i] < a[i 1]:i 1if i n - 1: # 每个非空子数组都可以移除return n …

普中STM32-PZ6806L开发板(STM32CubeMX创建项目并点亮LED灯)

简介 搭建一个用于驱动 STM32F103ZET6 GPIO点亮LED灯的任务;电路原理图 LED电路原理图 芯片引脚连接LED驱动引脚原理图 创建一个点亮LED灯的Keil 5项目 创建STM32CubeMX项目 New Project -> 单击 -> 芯片搜索STM32F103ZET6->双击创建 初始化时钟 调试设置 一…

双侧电源系统距离保护MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 系统原始数据 双侧电源系统模型如图所示&#xff1a; 仿真模型搭建 将线路AB分成Line1和Line2&#xff0c;将线路BC分成Line3和Line4&#xff0c;用三相电压电流测量模块作为系统母线&#xff0c;根据系统已…

洛谷 P1387 最大正方形 刷题笔记

P1387 最大正方形 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 找出一个 由数字1组成的最大正方形 输出该正方形的边长 &#xff1b; 思路 dp 画图模拟 可以发现 当 当前点a[i][j]1,满足构成正方形的初步条件 而当前点能构成的最大正方形长度 由它的左上角 左边和上边…

新手为什么跟着大型机构交易?fpmarkets总结理由

正所谓方向不对努力白费&#xff0c;这也就是为什么fpmarkets建议新手在刚开始的时候&#xff0c;跟着大型机构进行交易。 这些大型机构包括中央银行、巨额对冲基金、投资和保险公司等等&#xff0c;首先fpmarkets认为这些大型机构的交易量巨大&#xff0c;能够影响市场的走势。…

LeetCode刷题--- N 皇后

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​​​​http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递归…

ARCGIS PRO SDK 要素空间关系

一、要素与要素查询&#xff0c;返回的是bool值 1、 Touches 判断几何要素是否接触 Touches 如果 geometry1 与 geometry2 接触&#xff0c;则返回 true&#xff0c;否则 false。 touches GeometryEngine.Instance.Touches(Geometry1, Geometry2) 2、…

传感器原理与应用复习--电感式传感器

文章目录 上一篇自感式电感传感器差动变压器式传感器电涡流式传感器下一篇 上一篇 传感器原理与应用–传感器基本特性与应变式传感器 自感式电感传感器 将线圈通入电流产生磁场&#xff0c;而间隙的大小将影响磁场的大小&#xff0c;从而进行检测 变气隙式电感传感器&#xf…

2D transform 1-translate

移位&#xff1a;translate 缩放&#xff1a;scale 旋转&#xff1a;rotate 扭曲&#xff1a;skew <style>.outer {width: 200px;height: 200px;border: 2px solid black;margin-top: 100px;}.inner {width: 200px;height: 200px;background-color: pink;transform: t…