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,蜜汁不難???

相關文章
相關標籤/搜索