1. 程式人生 > >二叉查詢樹(BST),平衡二叉查詢樹(AVL),紅黑樹(RBT),B~/B+樹(B-tree)的比較

二叉查詢樹(BST),平衡二叉查詢樹(AVL),紅黑樹(RBT),B~/B+樹(B-tree)的比較

http://www.iteye.com/topic/614070

此少俠總結的特棒,直接收藏了。

我們這個專題介紹的動態查詢樹主要有: 二叉查詢樹(BST),平衡二叉查詢樹(AVL),紅黑樹(RBT),B~/B+樹(B-tree)。這四種樹都具備下面幾個優勢:

(1) 都是動態結構。在刪除,插入操作的時候,都不需要徹底重建原始的索引樹。最多就是執行一定量的旋轉,變色操作來有限的改變樹的形態。而這些操作所付出的代價都遠遠小於重建一棵樹。這一優勢在《查詢結構專題(1):靜態查詢結構概論 》中講到過。

(2) 查詢的時間複雜度大體維持在O(log(N))數量級上。可能有些結構在最差的情況下效率將會下降很快,比如BST。這個會在下面的對比中詳細闡述。

下面我們開始概括性描述這四種樹,並相互比較一下優劣。

1. 二叉查詢樹 (Binary Search Tree) 詳細見《查詢結構專題(2):二叉查詢樹 [BST]

很顯然,二叉查詢樹的發現完全是因為靜態查詢結構在動態插入,刪除結點所表現出來的無能為力(需要付出極大的代價)。

BST 的操作代價分析:

(1) 查詢代價: 任何一個數據的查詢過程都需要從根結點出發,沿某一個路徑朝葉子結點前進。因此查詢中資料比較次數與樹的形態密切相關。

當樹中每個結點左右子樹高度大致相同時,樹高為logN。則平均查詢長度與logN成正比,查詢的平均時間複雜度在O(logN)數量級上。

當先後插入的關鍵字有序時,BST退化成單支樹結構。此時樹高n。平均查詢長度為(n+1)/2,查詢的平均時間複雜度在O(N)數量級上。

(2) 插入代價: 新結點插入到樹的葉子上,完全不需要改變樹中原有結點的組織結構。插入一個結點的代價與查詢一個不存在的資料的代價完全相同。

(3) 刪除代價: 當刪除一個結點P,首先需要定位到這個結點P,這個過程需要一個查詢的代價。然後稍微改變一下樹的形態。如果被刪除結點的左、右子樹只有一個存在,則改變形態的代價僅為O(1)。如果被刪除結點的左、右子樹均存在,只需要將當P的左孩子的右孩子的右孩子的...的右葉子結點與P互換,在改變一些左右子樹即可。因此刪除操作的時間複雜度最大不會超過O(logN)。

BST效率總結 : 查詢最好時間複雜度O(logN),最壞時間複雜度O(N)。

插入刪除操作演算法簡單,時間複雜度與查詢差不多

2. 平衡二叉查詢樹 ( Balanced Binary Search Tree ) 詳細見《查詢結構專題(3):平衡二叉查詢樹 [AVL]

二叉查詢樹在最差情況下竟然和順序查詢效率相當,這是無法仍受的。事實也證明,當儲存資料足夠大的時候,樹的結構對某些關鍵字的查詢效率影響很大。當然,造成這種情況的主要原因就是BST不夠平衡(左右子樹高度差太大)。

既然如此,那麼我們就需要通過一定的演算法,將不平衡樹改變成平衡樹。因此,AVL樹就誕生了。

AVL 的操作代價分析:

(1) 查詢代價: AVL是嚴格平衡的BST(平衡因子不超過1)。那麼查詢過程與BST一樣,只是AVL不會出現最差情況的BST(單支樹)。因此查詢效率最好,最壞情況都是O(logN)數量級的。

(2) 插入代價: AVL必須要保證嚴格平衡(|bf|<=1),那麼每一次插入資料使得AVL中某些結點的平衡因子超過1就必須進行旋轉操作。事實上,AVL的每一次插入結點操作最多隻需要旋轉1次(單旋轉或雙旋轉)。因此,總體上插入操作的代價仍然在O(logN)級別上(插入結點需要首先查詢插入的位置)。

(3) 刪除代價:AVL刪除結點的演算法可以參見BST的刪除結點,但是刪除之後必須檢查從刪除結點開始到根結點路徑上的所有結點的平衡因子。因此刪除的代價稍微要大一些。每一次刪除操作最多需要O(logN)次旋轉。因此,刪除操作的時間複雜度為O(logN)+O(logN)=O(2logN)

AVL 效率總結 : 查詢的時間複雜度維持在O(logN),不會出現最差情況

AVL樹在執行每個插入操作時最多需要1次旋轉,其時間複雜度在O(logN)左右。

AVL樹在執行刪除時代價稍大,執行每個刪除操作的時間複雜度需要O(2logN)。

二叉平衡樹的嚴格平衡策略以犧牲建立查詢結構(插入,刪除操作)的代價,換來了穩定的O(logN) 的查詢時間複雜度。但是這樣做是否值得呢?

能不能找一種折中策略,即不犧牲太大的建立查詢結構的代價,也能保證穩定高效的查詢效率呢? 答案就是:紅黑樹。

RBT 的操作代價分析:

(1) 查詢代價:由於紅黑樹的性質(最長路徑長度不超過最短路徑長度的2倍),可以說明紅黑樹雖然不像AVL一樣是嚴格平衡的,但平衡效能還是要比BST要好。其查詢代價基本維持在O(logN)左右,但在最差情況下(最長路徑是最短路徑的2倍少1),比AVL要略遜色一點。

(2) 插入代價:RBT插入結點時,需要旋轉操作和變色操作。但由於只需要保證RBT基本平衡就可以了。因此插入結點最多隻需要2次旋轉,這一點和AVL的插入操作一樣。雖然變色操作需要O(logN),但是變色操作十分簡單,代價很小。

(3) 刪除代價:RBT的刪除操作代價要比AVL要好的多,刪除一個結點最多隻需要3次旋轉操作。

RBT 效率總結 : 查詢 效率最好情況下時間複雜度為O(logN),但在最壞情況下比AVL要差一些,但也遠遠好於BST。

插入和刪除操作改變樹的平衡性的概率要遠遠小於AVL(RBT不是高度平衡的)。因此需要的旋轉操作的可能性要小,而且一旦需要旋轉,插入一個結點最多隻需要旋轉2次,刪除最多隻需要旋轉3次(小於AVL的刪除操作所需要的旋轉次數)。雖然變色操作的時間複雜度在O(logN),但是實際上,這種操作由於簡單所需要的代價很小。

對於在記憶體中的查詢結構而言,紅黑樹的效率已經非常好了(實際上很多實際應用還對RBT進行了優化)。但是如果是資料量非常大的查詢呢?將這些資料全部放入記憶體組織成RBT結構顯然是不實際的。實際上,像OS中的檔案目錄儲存,資料庫中的檔案索引結構的儲存.... 都不可能在記憶體中建立查詢結構。必須在磁碟中建立好這個結構。那麼在這個背景下,RBT還是一種好的選擇嗎?

在磁碟中組織查詢結構,從任何一個結點指向其他結點都有可能讀取一次磁碟資料,再將資料寫入記憶體進行比較。大家都知道,頻繁的磁碟IO操作,效率是很低下的(機械運動比電子運動要慢不知道多少)。顯而易見,所有的二叉樹的查詢結構在磁碟中都是低效的。因此,B樹很好的解決了這一個問題。

B-Tree的操作代價分析:

(1) 查詢代價: B-Tree作為一個平衡多路查詢樹(m-叉)。B樹的查詢分成兩種:一種是從一個結點查詢另一結點的地址的時候,需要定位磁碟地址(查詢地址),查詢代價極高。另一種是將結點中的有序關鍵字序列放入記憶體,進行優化查詢(可以用折半),相比查詢代價極低。而B樹的高度很小,因此在這一背景下,B樹比任何二叉結構查詢樹的效率都要高很多。而且B+樹作為B樹的變種,其查詢效率更高。

(2)插入代價: B-Tree的插入會發生結點的分裂操作。當插入操作引起了s個節點的分裂時,磁碟訪問的次數為h(讀取搜尋路徑上的節點)+2s(回寫兩個分裂出的新節點)+1(回寫新的根節點或插入後沒有導致分裂的節點)。因此,所需要的磁碟訪問次數是h+2s+1,最多可達到3h+1。因此插入的代價是很大的。

(3)刪除代價:B-Tree的刪除會發生結點合併操作。最壞情況下磁碟訪問次數是3h=(找到包含被刪除元素需要h次
讀訪問)+(獲取第2至h層的最相鄰兄弟需要h-1次讀訪問)+(在第3至h層的合併需要h-2次寫
訪問)+(對修改過的根節點和第2層的兩個節點進行3次寫訪問)

B-Tree效率總結: 由於考慮磁碟儲存結構,B樹的查詢、刪除、插入的代價都遠遠要小於任何二叉結構樹(讀寫磁碟次數的降低)。

動態查詢樹結構的對比:

(1) 平衡二叉樹和紅黑樹 [AVL PK RBT]

AVL 和RBT 都是二叉查詢樹的優化。其效能要遠遠好於二叉查詢樹。他們之間都有自己的優勢,其應用上也有不同。

結構對比: AVL的結構高度平衡,RBT的結構基本平衡。平衡度AVL > RBT.

查詢對比: AVL 查詢時間複雜度最好,最壞情況都是O(logN)。

RBT 查詢時間複雜度最好為O(logN),最壞情況下比AVL略差。

插入刪除對比: 1. AVL的插入和刪除結點很容易造成樹結構的不平衡,而RBT的平衡度要求較低。因此在大量資料插入的情況下,RBT需要通過旋轉變色操作來重新達到平衡的頻度要小於AVL。

2. 如果需要平衡處理時,RBT比AVL多一種變色操作,而且變色的時間複雜度在O(logN)數量級上。但是由於操作簡單,所以在實踐中這種變色仍然是非常快速的。

3. 當插入一個結點都引起了樹的不平衡,AVL和RBT都最多需要2次旋轉操作。但刪除一個結點引起不平衡後,AVL最多需要logN 次旋轉操作,而RBT最多隻需要3次。因此兩者插入一個結點的代價差不多,但刪除一個結點的代價RBT要低一些。

4. AVL和RBT的插入刪除代價主要還是消耗在查詢待操作的結點上。因此時間複雜度基本上都是與O(logN) 成正比的。

總體評價:大量資料實踐證明,RBT的總體統計效能要好於平衡二叉樹。

(2) B~樹和B+樹 [ B~Tree PK B+Tree]

B+樹是B~樹的一種變體,在磁碟查詢結構中,B+樹更適合檔案系統的磁碟儲存結構。

結構對比: B~樹是平衡多路查詢樹,所有結點中都包含了待查關鍵字的有效資訊(比如檔案磁碟指標)。每個結點若有n個關鍵字,則有n+1個指向其他結點的指標。

B+樹嚴格意義上說已經不是樹,它的葉子結點之間也有指標連結。B+樹的非終結點中並不含有關鍵字的資訊,需要查詢的關鍵字的全部資訊都包含在葉子結點上。非終結點中只作為葉子結點關鍵字的索引而存在。

查詢對比:1. 在相同數量的待查資料下,B+樹查詢過程中需要呼叫的磁碟IO操作要少於普通B~樹。由於B樹所在的磁碟儲存背景下,因此B+樹的查詢效能要好於B~樹。

2. B+樹的查詢效率更加穩定,因為所有葉子結點都處於同一層中,而且查詢所有關鍵字都必須走完從根結點到葉子結點的全部歷程。因此同一顆B+樹中,任何關鍵字的查詢比較次數都是一樣的。而B樹就不一定了,可能查詢到某一個非終結點就結束了。

插入刪除對比: B+樹與B~樹在插入刪除操作中的效率是差不多的。

總體評價:在應用背景下,特別是檔案結構儲存中。B+樹的應用要更多,其效率也要比B~樹好。

字串查詢結構

這次專題所講的BST、AVL、BRT、B~Tree等可以勝任對任何關鍵字資料進行查詢。但對字串的查詢(字串匹配)結構,有專門的結構和演算法。詳見:《KMP演算法 》,《Trie Tree