k-d tree 学习笔记

以下是一些奇怪的链接有兴趣的可以看看:

https://blog.sengxian.com/algorithms/k-dimensional-tree

http://zgjkt.blog.uoj.ac/blog/1693

https://en.wikipedia.org/wiki/K-d_tree

http://homes.ieu.edu.tr/hakcan/projects/kdtree/kdTree.html

k-d tree就是一个把一个平面(或超平面)划分的东西…

例如一维情况就是在划分一个数轴,这时就成了我们喜闻乐见的二叉搜索树。

二维情况

用横线和竖线,每次把一个矩形瓜分成两半。

还有三维的,四维的,以此类推…… k维的就叫 k-d tree。

这篇文章就讲一下二维的k-d tree。

每一次我们对于k-d tree上的一个点,我们要沿着某一个轴切开,那么这个轴怎么确定呢?一个切x轴的点的孩子就切y轴,切y轴的点的孩子就切x轴,轮流切分,这样做比较优秀,又比较好写。

例如这个点是切x轴的,为了查询比较和谐,那么它的左子树所有点都要x比它小,右子树所有点都要x比它大(当然也可以是等于),这点与二叉搜索树是一致的)。

①建树

比如我现在有n个点,现在要建成一棵美观的k-d tree,怎么建呢?

在bst中我们一般是选比较中间的一个数,然后递归下去建树。

k-d tree中也是类似的,不过我们要确保当前节点的左子树的点当前维度都比它小,右子树的点当前维度都比它大。我们可以每一次在当前层sort一下当前维度,然后选出中位数?

注意到我们只要让左边比较小,右边比较大,中间比较中间就行了,sort一下显然有点浪费,到了下一维度又要重新sort。这里我们使用stl中的nth_element函数,该函数内部用了quick_select算法(就是快速排序的前半部分)来干这件事,复杂度O(n)。

void nth_element(first,nth,last[,cmp]) (比较函数可选)

对[first,last)的元素重新布置,使得nth的元素在sort之后应该在的位置上,而前面的元素都不大于它,后面的元素都不小于它

这样我们就可以建出一棵比较平衡的k-d tree啦。参考线段树建树的复杂度证明很容易发现这玩意儿也是O(nlogn)的。

②插入

额似乎这玩意儿没必要讲,也就是和当前点的当前维度比较一下然后插入就行。

对于一棵比较平衡的k-d tree,插入显然是O(logn)的。

③询问

首先我们要解决的是…k-d tree有卵用?

显然k-d tree可以被当作是一个比较厉害的k维(本文中是二维)线段树!在这上面可以打tag,可以搞询问(划分矩形的时候注意一下),甚至还可以搞segment tree beats(参见吉司机的集训队论文)

但是二维情况下k-d tree当作线段树用处不大…因为前有二维树状数组/二维线段树,后有cdq分治、整体二分啥的…除非出题人丧心病狂又卡空间又要在线

正常的k-d tree是用来询问最近点的利器!

比如有一道这样的题(bzoj2648),要求每次询问离一个给定点最近(曼哈顿距离)的黑点和加入一个黑点。

真是良心出题人!

查找时我们可以这么做,先把ans设成inf,然后我们从根结点开始递归查询。

对于k-d tree上的一个节点,先用这个点更新答案。然后对于它的两个孩子,优先选择离当前点近的一个矩形(注意这个值显然不一定能取到)递归更新答案,然后更新完答案如果到另一个儿子的那个矩形距离比答案小就也用另一个儿子递归更新答案。

对于一棵比较平衡的k-d tree,这样查询的复杂度最坏是O(sqrt(n))的,一般是O(log(n))的。

(这个“一般”的性质就跟spfa所谓的O(ke)差不多)

可以注意到这里的“近”“距离”对于欧几里得距离与曼哈顿距离都适用。

至于k近点对也比较简单,我们维护一个大根堆,每次比较堆顶啥的就行。

显然这样的复杂度比刚才要多一个klogk。

④一些小问题

有没有注意到刚才的复杂度上有若干个类似“比较平衡”的字眼?

是的,k-d tree的性质就与一棵没有旋转的二叉查找树差不多。

如果建完树不再插入,这时k-d tree是十分平衡的,可以保证查询的一切复杂度。

如果建完树还插入或者干脆不建树直接插入,这时k-d tree对于随机数据仍然是“十分平衡”的,而随便构造一个数据(例如1,1 2,2 3,3...这样的数据)就可以成功地卡飞k-d tree。

所以如果又有插入又有询问,你只能假装数据是随机的...

今天先写到这里吧......代码等有时间再补吧(虽然我不太清楚什么时候才会填上)

时间: 2024-08-09 10:44:45

k-d tree 学习笔记的相关文章

Link Cut Tree学习笔记

从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子树信息 小结 动态树问题和Link Cut Tree 动态树问题是一类要求维护一个有根树森林,支持对树的分割, 合并等操作的问题. Link Cut Tree(林可砍树?简称LCT)是解决这一类问题的一种数据结构. 一些无聊的定义 Link Cut Tree维护的是动态森林中每棵树的任意链剖分. P

矩阵树定理(Matrix Tree)学习笔记

如果不谈证明,稍微有点线代基础的人都可以在两分钟内学完所有相关内容.. 行列式随便找本线代书看一下基本性质就好了. 学习资源: https://www.cnblogs.com/candy99/p/6420935.html http://blog.csdn.net/Marco_L_T/article/details/72888138 首先是行列式对几个性质(基本上都是用数学归纳法证): 1.交换两行(列),行列式取相反数 2.由1.得若存在两行(列)完全相同则行列式为0 3.上(下)三角行列式即主

统计学习方法 (第3章)K近邻法 学习笔记

第3章 K近邻法 k近邻算法简单.直观:给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的k个实例,这k个实例的多数属于某个类,就把该输入实例分为这个类.当K=1时,又称为最近邻算法,这时候就是将训练数据集中与x最邻近点作为x的类. 3.1 k近邻模型 模型由三个基本要素--距离度量.k值得选择.和分类决策规则决定. 3.1.1 距离度量 p=2时,称为欧式距离,p=1时,称为曼哈顿距离. 3.1.2 k值的选择 k 值的选择会对k 近邻法的结果产生重大影响.如果选择较小的k

机器学习2—K近邻算法学习笔记

Python3.6.3下修改代码中def classify0(inX,dataSet,labels,k)函数的classCount.iteritems()为classCount.items(),另外print在Python新版本下是函数,print后面需加上一对括号,否则执行会报错.第二章代码修改如下. from numpy import * import operator from os import listdir def classify0(inX, dataSet, labels, k)

支配树学习笔记

支配树(dominator tree) 学习笔记 学习背景 本来本蒟蒻都不知道有一个东西叫支配树……pkuwc前查某位的水表看见它的大名,甚感恐慌啊.不过好在pkuwc5道题(嗯?)都是概率期望计数,也不知是好还是不好,我在这些方面也只是不好不差……扯远了. 考挂之后也没什么心思干别的,想起支配树这个东西,于是打算学一下. 技能介绍(雾) 支配树是什么?不如直接讲支配树的性质,从性质分析它的定义. 先大概讲一下它是来求什么的. 问题:我们有一个有向图(可以有环),定下了一个节点为起点s.现在我们

Ext.Net学习笔记22:Ext.Net Tree 用法详解

Ext.Net学习笔记22:Ext.Net Tree 用法详解 上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat="server"> <Root> <ext:Node Text="根节点" Expanded="true"> <Children> <ext:Node Text="节点1" Expand

这是三天的linux学习笔记,大神可以指教,别喷我,我新手。

20140825.学习笔记开启新终端    ctrl+shift+n关闭终端    alt+F4扩大终端    ctrl+shift+"+"缩小终端    ctrl+"-"开启新的终端标签    ctrl+shift+t关闭终端标签    ctrl+shift+w标签之间的切换    alt+标签对应的编号切换到真实终端tty3   ctrl+alt+F3tty回到图形     alt+F1或者F7 快捷键设置终端--->编辑--->键盘快捷键 设置终端

Query意图分析:记一次完整的机器学习过程(scikit learn library学习笔记)

所谓学习问题,是指观察由n个样本组成的集合,并根据这些数据来预测未知数据的性质. 学习任务(一个二分类问题): 区分一个普通的互联网检索Query是否具有某个垂直领域的意图.假设现在有一个O2O领域的垂直搜索引擎,专门为用户提供团购.优惠券的检索:同时存在一个通用的搜索引擎,比如百度,通用搜索引擎希望能够识别出一个Query是否具有O2O检索意图,如果有则调用O2O垂直搜索引擎,获取结果作为通用搜索引擎的结果补充. 我们的目的是学习出一个分类器(classifier),分类器可以理解为一个函数,

OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 2013-03-23 17:44 16963人阅读 评论(28) 收藏 举报 分类: 机器视觉(34) 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] KAZE系列笔记: OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 OpenCV学习笔记(28)KA