KD-Tree

yyb简单的学习KD-Tree

感受最近一直在学东西来着。函数

至于缘由?学习

仍是我太弱了,每次看一道题:啥?这是什么?根本没学过啊。ui

索性这段时间就多学点新知识吧。spa

提及来,我如今最近根本不会取标题名字了,就随意一点吧。翻译

仍是这样一个一个的\(part\)写起来比较舒服。code

KD-Tree是什么?

咱们先来理解一下\(K\)\(D\)\(Tree\)排序

首先\(Tree\)是什么?你本身回答吧。递归

而后\(K\)是什么?\(K\)固然就是\(K\)啊,仍是什么?element

\(D\)?彷佛是\(demensional\)??也就是维度的意思博客

这样就能解释为啥\(K\)就是\(K\)

因此翻译过来就是“K维树”咯。

所以,\(KD-Tree\)用来分割\(K\)维空间,而后能够在上面搞各类各样的事情?

彷佛就是这样的。

怎么分割空间啊?

显然的,在咱们的空间中,有一堆的点。

咱们如今要处理他们。

因此咱们选择任意一个维度排序

而后选择中间那个点的这一维来分割空间。

按照这一维排序后左右就分红了两部分。

这样子就能够分割空间了。(有一个\(STL\)的函数叫作\(nth\_element\),能够了解一下)

(据说维度不能那么随意的选择,好比你一直只按照一个维度划分彷佛就不是很好?)

(网上的博客主要是推荐按照每一个维度依次分割,若是全部维度都分割完了就再从第一个开始循环)

(彷佛还有一种更好的方法?算下方差什么的,反正我是不打算用这种啦)

怎么算答案啊

咱们如今已经把空间给分割,对于每一块分割出来的空间,里面有若干个点。

咱们对于这些点维护一些信息,在回答询问的时候,利用这些信息估算一下答案,

若是最有状况下的答案不优于当前答案,咱们就不在这个空间内计算答案。

听着颇有道理?

怎么越听越以为像剪枝?

恩,好像就是剪枝诶!

因此咱们的\(KD-Tree\)也是一个暴力?

反正我是这么认为的。

怎么写啊

首先咱们须要一个\(Build\)函数来构建\(KD-Tree\)

因而它大概长成这个样子

int Build(int l,int r,int nD)
{
    int x=(l+r)>>1;D=nD;
    nth_element(&a[l],&a[x],&a[r+1]);
    t[x].d[0]=t[x].mn[0]=t[x].mx[0]=a[x].d[0];
    t[x].d[1]=t[x].mn[1]=t[x].mx[1]=a[x].d[1];
    if(l<x)ls=Build(l,x-1,nD^1),update(x,ls);
    if(r>x)rs=Build(x+1,r,nD^1),update(x,rs);
    return x;
}

对于插入操做,咱们模仿\(Build\)的这个递归操做,

对于当前节点所掌控的空间进行当前维度的比较,检查应该分像左侧仍是右侧。

等等?这听起来怎么这么像\(SBT\)??反正我也是这么以为的

也许\(KD-Tree\)就是\(SBT\)在空间上的拓展???

话说回来,\(KD-Tree\)在处理实际问题的时候,不一样的剪枝函数要本身仔细思考,这样才可以更快。

据说有的时候由于插点插得太多了,致使\(KD-Tree\)变得很是的不平衡,

咱们能够相似替罪羊树同样把它推倒重建。

对于每一个节点咱们额外维护一个\(size\)

每次\(check\)一下当前节点左右子树的\(size\)的比值时候超过了设定的\(alpha\)

若是超过了直接拍扁重建一次就好啦

qaq,蜜汁不难???

相关文章
相关标签/搜索