k
維檢索樹類似於二叉檢索樹,不同的是,它能同時提供多維度屬性的檢索。
k維(從
0開始計維數)檢索樹的定義:
k維檢索樹是乙個
n層的二叉樹(根節點為第
0層,依次往下為第
1,2..n-1
層),對於樹中第
n層的每個節點,其左子樹所有節點的第
n%k維屬性小於或等於該節點的第
n%k維屬性;其右子樹所有節點的第
n%k維屬性都大於或等於該節點的第
n%k維屬性。通俗的講,就是將整個樹的層數迴圈標記為0到
k-1,在第
0層比較第
0為屬性,在第
1層比較第
1層屬性,依此類推。
假設a-g
代表二維空間的點(由
x,y二維座標標示
),則依次插入
a-g節點到樹中會構成如下所示的樹。
插入a樹為空,
a作為根節點
插入b
與a比較第0
維屬性,進入左子樹,左子樹為空,直接插入
插入c
與a比較第0
維屬性,進入右子樹,右子樹為空,直接插入
插入d
與a比較第0
維屬性,進入左子樹,與
b比較第
1維屬性,進入左子樹…
插入e 與
a比較第
0維屬性,進入左子樹,與
b比較第
1維屬性,進入右子樹…
插入f 與
a比較第
0維屬性,進入右子樹,與
c比較第
1維屬性,進入右子樹…
插入g 與
a比較第
0維屬性,進入左子樹,與
b比較第
1維屬性,進入左子樹,與d
比較第0
維屬性,進入左子樹…
演算法時間複雜度:
查詢:從根節點逐層比較,直到遇到目標或者子樹為空,時間複雜度為
o(logn)
。插入:從根節點逐層比較,按照定義的規則直到遇到葉子節點,時間複雜度為
o(logn)
。刪除:對於葉子節點,或只有單分支子樹的節點,直接刪除,否則找到右子樹的最左節點或左子樹的最右節點,替換掉被刪節點,演算法複雜度
o(logn)
。優化:將樹優化為平衡樹,將樹的節點匯出至
vector
中,並清空樹,將
vector
集合按第一維屬性,分成兩堆,左邊比中間元素小,右邊比中間元素大(
nth-element
),將中間元素插入到樹中,遞迴將左右兩堆的元素插入到左子樹、右子樹(比較時根據層數比較對應的維度值)。優化的時間複雜度為o(
nlogn
)。區間查詢:從根節點起,檢查根節點是否符合條件,如果符合加入至結果集中;如果左子樹跟目標區間有交集,遞迴查詢左子樹;如果右子樹跟目標區間有交集,查詢右子樹。(設定乙個動態區間,初始時與目標區間相同,進入左子樹,則要更新動態區間對應維度的上限;若進入右子樹,則要更新動態區間對應維度的上限;通過判斷動態和目標區間是否有交集可以看出需要進入左右子樹,從而減少查詢空間)。
更詳細的了解參考**:
multidimensional binary search trees used for associative searching
libkdtree++是乙個
c++實現的
kdtree lib
,提供了
insert
、erase
、optimise
、find_exact
、find_within_range
、find_nearest
等介面。
find_with_range(val, range, outputiterator)
不能滿足需求,因只能指定每維屬性在
val[k] – range
到val[k] +
range
的範圍內。因為需要支援任意區間查詢,而
kdtree++
沒有提供
需要的介面,我在
kdtree
的實現中增加了
find_within_range(vmin,
vmax, outputiterator)
介面,同時需要給
region
新增乙個建構函式。
檢索樹 刪除演算法
為了記錄下檢索樹刪除演算法,我來發個部落格開心一下。如何刪除檢索樹中的元素?想要刪除檢索樹中的結點,步驟 找到要刪除結點 刪除結點 if x q data 向左搜尋 else 向右搜尋 if p 未找到 return 0 if p rson p沒有右兒子,用左兒子代替p else 如果p是其父結點的...
k近鄰法中kd tree樹的建立
經過一天努力實現了kd tree樹二維的建立,但是 只適用於二維,這是令人遺憾的地方。在這個過程中學到了不少東西,特別是對vector的一些用法,多了更多的了解。思路 建立樹時,傳遞vector為形參,以第n 2維為變數,對結構體vector排序,找出中位數,奇數找中間,偶數取第 n 2 1個,以它...
離散化 和多維線段樹
分類 練習 2013 05 25 10 07 196人閱讀收藏 舉報 acmc 資料結構 離散化 題目大意 給出 n 個矩形的 左下 和 右上 頂點座標,求面積並 思路 由於座標值為實數,所以不能直接用陣列模擬,要先將所有座標值離散化處理 cpp view plain copy print?incl...