1. 程式人生 > >演算法解析:KD樹

演算法解析:KD樹

1. 概述

KD樹是一種查詢索引結構,廣泛應用於資料庫索引中。從概念的角度講,它是一種高緯資料的快速查詢結構,本文首先介紹1維資料的索引查詢,然後介紹2維KD樹的建立和查詢,相關定理和推論也簡單列出,本文爭取用15分鐘的時間,讓大家快速理解KD樹。

2. 1維資料的查詢

假設在資料庫的表格T中儲存了學生的語文成績chinese、數學成績math、英語成績english,如果要查詢語文成績介於30~93分的學生,如何處理?假設學生數量為N,如果順序查詢,則其時間複雜度為O(N),當學生規模很大時,其效率顯然很低,如果使用平衡二叉樹,則其時間複雜度為O(logN),能極大地提高查詢效率。平衡二叉樹示意圖為:

圖1:平衡二叉樹示意圖

對於1維資料的查詢,使用平衡二叉樹建立索引即可。如果現在將查詢條件變為:語文成績介於30~93,數學成績結餘30~90,又該如何處理呢?

如果分別使用平衡二叉樹對語文成績和數學成績建立索引,則需要先在語文成績中查詢得到集合S1,再在數學成績中查詢得到集合S2,然後計算S1和S2的交集,若|S1|=m,|S2|=n,則其時間複雜度為O(m*n),有沒有更好的辦法呢?

3. KD樹

針對多維資料索引,是否也存在類似的一維的索引方法呢?先看2維資料的集合示意圖:

圖2: 2維資料示意圖

如果先根據語文成績,將所有人的成績分成兩半,其中一半的語文成績<=c1,另一半的語文成績>c1,分別得到集合S1,S2;然後針對S1,根據數學成績分為兩半,其中一半的數學成績<=m1,另一半的數學成績>m1,分別得到S3,S4,針對S2,根據數學成績分為兩半,其中一半的數學成績<=m2,另一半的數學成績>m2,分別得到S5,S6;再根據語文成績分別對S3,S4,S5,S6繼續執行類似劃分得到更小的集合,然後再在更小的集合上根據數學成績繼續,...

上面描述的就是構建KD樹的基本思路,其構建後的KD樹如下圖所示:

圖3: KD樹示意圖

如圖所示,l1左邊都是語文成績低於45分,l1右邊都是語文成績高於45分的;l2下方都是語文成績低於45分且數學成績低於50分的,l2上方都是語文成績低於45分且數學成績高於50分的,後面以此類推。下面的圖示,更清晰地表示了KD樹的結構及其對應的二叉樹:

圖4: KD樹及對應的二叉樹

在瞭解了KD樹的基本原理後,剩下的工作就是如何構建KD樹以及如何在KD樹上查詢了。

3.1 KD樹構建演算法

相對而言,構建KD樹是針對高維資料,需要針對每一維都進行二分,針對二維資料的KD樹構建演算法如下圖5所示:

圖5:KD樹構建演算法

其中的P表示待構建的元素集合,depth表示當前是KD樹的第幾層,如果depth是偶數,通過縱向線對集合進行劃分;如果depth是奇數,通過橫向線進行劃分(3~5行);第6、7行遞迴進行KD樹中子樹的構建。

圖5中的演算法時間複雜度為:O(nlogn),感興趣的同學可以寫出遞推公式公式進行推到,演算法導論中專門講了這個遞推公式。

3.2 KD樹查詢演算法

在構建了KD樹的基礎上,如何進行查詢其實是一個相對簡單的問題了,在這裡需要注意的是,在KD樹中每一層劃分所依據的是哪一維的資料,其它的根二叉樹其實沒有差別。KD樹查詢演算法如下圖所示:

圖6: 查詢演算法

圖6中演算法的v表示KD樹中當前搜尋的子樹,R表示是一個高維資料的區域,區域的概念如圖7所示:

圖7: 區域示意圖

如果v是葉子結點且屬於區域R,則直接返回(第1行);如果v是非葉子結點,則比較R與v的左子樹lc(v)是否有交集,如果有且lc(v)完全被R覆蓋,則lc(v)是所查詢結果的一部分,如果不是完全覆蓋,則遞迴查詢lc(v)(36行);對右子樹也是類似的操作(710)。演算法的時間複雜度為:O(sqrt(n) + k),其中k是最後的結果中元素的個數,其遞推公式公式為:

圖8: KD樹查詢遞推公式

上述演算法中的二維也可升級為3維,其思維方式與從1維升級到2維一致,相應的構建演算法和查詢演算法也與2維的一致,感興趣的童鞋可以分析相應演算法的時間複雜度。

4. 小結

本文以從1維資料索引跳變到2維資料索引的方式,引出了KD樹,並介紹了KD樹的構建與索引查詢演算法。KD樹主要應用在高維資料索引,特別是空間資料庫的索引,x和y分別表示經度和緯度,能較好的處理空間上的查詢效率問題,如果在x和y再加一個時間維度,也能較好地處理時空資料索引查詢。

作者:CodingTech 連結:https://www.jianshu.com/p/ffe52db3e12b 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。