1. 程式人生 > >KD-Tree學習筆記

KD-Tree學習筆記

  參考:https://trinkle23897.github.io/pdf/K-D%20Tree.pdf

  KD-Tree是一種維護K維空間點的類似BST的資料結構。絕大多數時候只用來維護二維空間的點,因為維度越高複雜度越辣雞。下面只考慮平面上的KD-Tree,即2D-Tree。

  KD-Tree以分割平面來實現類似BST的建樹。具體的,取該座標中位數(即相當於劃了一條直線)將點集劃分成兩部分,剛好被取作中位數的點放在該節點,並記錄該節點管轄的平面區域範圍。剩餘的點分別放進左右兒子,遞迴建樹。由於只需要按中位數分割,可以使用nth_element去掉排序的log。每次用來劃分的維度應交替(或者隨機,總之越均勻越好)選擇,以保證之後查詢的玄學複雜度。建樹複雜度顯然是O(nlogn)。

  KD-Tree最常用的是用來查詢某點的曼哈頓/歐幾里得距離最近點。具體做法實際上就是A*,即考慮應該往一個節點的左兒子還是右兒子繼續查詢時,通過節點的平面區域範圍給它一個估價函式(當然不劣於實際),如果估價劣於已經找到的最優答案,當然不繼續遞迴,否則優先遞迴估價較優的。據說複雜度隨機O(logn),能卡到O(√n)。

  同時KD-Tree還可以滋磁矩形查詢。具體做法實際上就是線段樹,即如果當前節點所管轄的範圍被查詢範圍包含,直接返回該節點答案,否則暴力遞迴左右節點查詢。絲毫不會證複雜度。

  插入一個點是非常正常的操作,但是在KD-Tree裡插入點有和BST一樣的問題,即一不小心就不平衡了。如果可以離線,事實上可以先給所有點建好KD-Tree,將一開始不存在的點打上標記,實際插入該點時清除標記啟用該點。如果強制線上,則使用替罪羊式的重構。