学习笔记:KD-TREE

本文详细介绍了KD-Tree数据结构,包括其原理、分割策略、STL函数:nth_element的应用,以及在不同维度下的性能分析。重点讨论了KD-Tree在计算几何中的作用,如何进行插入和搜索操作,以及如何利用 nth_element 函数实现超平面分割。此外,文章还提供了实现KD-Tree时应注意的编程细节和相关题目的推荐。
摘要由CSDN通过智能技术生成

前言

一个感觉特别单一的数据结构啊,Po大爷才写两个这个题呢。

然后仔细研究了一下KD-TREE为什么要这样做,发现其中的每一个操作都是很巧妙的。

原理简述(瞎逼逼)

KD-Tree确实应该算是计算几何的一种东西了吧,可以看作线段树的高维推广还自带离散功能。

KD-Tree也是一个二叉树,并且除了叶子结点外,每个结点都代表了一堆点,叶子结点则代表了一个,和线段树是很像的。

每个点我们要维护它的各个坐标的最大值以及最小值,这是有利于后面的搜索操作的。

它的分割原则是对于一个K维的一些点,用一个超平面(k-1维)来把这堆点分割成平均的两部分,如何平均,用一些STL的nth_element函数就可以了(下面有介绍)

在分割的时候,我们根据不同的层数,不停的转变被分割的那一维,本来一直用一维也是可以的,但是对于接下来的搜索操作就不是很有利了。

现在讲一下一个搜索操作:对于一个结点,我们要找最大值/最小值,就按照我们对于一堆点坐标最值来贪心地去选择顺序搜索,并且及时剪枝,所以这似乎就是一个优雅的暴力。不过权威证明,它的时间复杂度是O(n^1/2),并且在实际运行中跑得贼快。这里也可以看我们为什么要不停换维度分割,我们让一堆点尽量存在在一个比较‘方’的区间里面,有利于我们的搜索。(仔细体会一下嘛)

插入操作就按照划分方式往下放就行了,但是由于插入过多可能不平衡,所以我们可以利用替罪羊树的思想在一定情况下进行暴力重构。

时间复杂度的话:

建树是O(nlogn)

其它大概都是O(logn)

搜索是O(n^(1-(1/k)))但是实际效果好很多

再谈KD-Tree

KD-Tree的时间复杂度随着维度升高并不是线性增长的,一般二维还是sqrt(n)的级别,那么和log^2(n),基本上是没有差距的,但是更高纬度可能就不行了,所以最好是保证在二维之内,KDTree的维护有两个方式,一个是暴力重构,一个是一来就把数据全部建好。

然而KD-Tree找距离是可以被卡成O(n)的,但是毒瘤出题人要是偏要故意卡那就认了呗。不过一般数据结构不知道能不能卡。

数据的限制一般是很难降维的,毕竟咱不是三体,所以一旦分析除了,最好不要尝试降维,而是找合适的数据结构。

KD-Tree查找时间复杂度的由来:由于为了贪心查找距离,所以我们要求当前空间尽量方,这样比较好找,但是就会出现一个区间本来都抵满了还要被继续分割的情况,所以是比logn^2要大一些的,而且维度越高越大。

关于维度的选择,不要觉得只是拿来玩的,由于不同维度可能有不同的性质,比如区间加法或者,

所以遇到二维以内的在线问题就直接上KD-Tree吧, 也就是说懒得去写树套树了,但是维度更高就尝试用其它方法降维,比如二分、可持久化,如果可以用莫队,CDQ什么的也不要用KD-Tree,因为KD-Tree时间复杂度不好保证。

注意二分也是可

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值