概念算法
二叉查找樹又稱二叉搜索樹,二叉排序樹,特色以下:數據庫
任何一個數據的查找過程都須要從根結點出發,沿某一個路徑朝葉子結點前進。所以查找中數據比較次數與樹的形態密切相關。 數組
當樹中每一個結點左右子樹高度大體相同時,樹高爲logN。則平均查找長度與logN成正比,查找的平均時間複雜度在O(logN)數量級上。 性能
當前後插入的關鍵字有序時,BST退化成單支樹結構。此時樹高n。平均查找長度爲(n+1)/2,查找的平均時間複雜度在O(N)數量級上。優化
新結點插入到樹的葉子上,徹底不須要改變樹中原有結點的組織結構。插入一個結點的代價與查找一個不存在的數據的代價徹底相同。指針
當刪除一個結點P,首先須要定位到這個結點P,這個過程須要一個查找的代價。而後稍微改變一下樹的形態。若是被刪除結點的左、右子樹只有一個存在,則改變形態的代價僅爲O(1)。若是被刪除結點的左、右子樹均存在,只須要將當P的左孩子的右孩子的右孩子的…的右葉子結點與P互換,在改變一些左右子樹便可。所以刪除操做的時間複雜度最大不會超過O(logN)。排序
查找最好時間複雜度O(logN),最壞時間複雜度O(N)。 索引
插入刪除操做算法簡單,時間複雜度與查找差很少。內存
二叉查找樹在最差狀況下居然和順序查找效率至關,這是沒法仍受的。事實也證實,當存儲數據足夠大的時候,樹的結構對某些關鍵字的查找效率影響很大。固然,形成這種狀況的主要緣由就是BST不夠平衡(左右子樹高度差太大)。既然如此,那麼咱們就須要經過必定的算法,將不平衡樹改變成平衡樹。所以,AVL樹就誕生了。效率
AVL是嚴格平衡的BST(平衡因子不超過1)。那麼查找過程與BST同樣,只是AVL不會出現最差狀況的BST(單支樹)。所以查找效率最好,最壞狀況都是O(logN)數量級的。
AVL必需要保證嚴格平衡(|bf|<=1),那麼每一次插入數據使得AVL中某些結點的平衡因子超過1就必須進行旋轉操做。事實上,AVL的每一次插入結點操做最多隻須要旋轉1次(單旋轉或雙旋轉)。所以,整體上插入操做的代價仍然在O(logN)級別上(插入結點須要首先查找插入的位置)。
AVL刪除結點的算法能夠參見BST的刪除結點,可是刪除以後必須檢查從刪除結點開始到根結點路徑上的全部結點的平衡因子。所以刪除的代價稍微要大一些。每一次刪除操做最多須要O(logN)次旋轉。所以,刪除操做的時間複雜度爲O(logN)+O(logN)=O(2logN)
查找的時間複雜度維持在O(logN),不會出現最差狀況
AVL樹在執行每一個插入操做時最多須要1次旋轉,其時間複雜度在O(logN)左右。
AVL樹在執行刪除時代價稍大,執行每一個刪除操做的時間複雜度須要O(2logN)。
二叉平衡樹的嚴格平衡策略以犧牲創建查找結構(插入,刪除操做)的代價,換來了穩定的O(logN) 的查找時間複雜度。可是這樣作是否值得呢?
能不能找一種折中策略,即不犧牲太大的創建查找結構的代價,也能保證穩定高效的查找效率呢? 答案就是:紅黑樹。
因爲紅黑樹的性質(最長路徑長度不超過最短路徑長度的2倍),能夠說明紅黑樹雖然不像AVL同樣是嚴格平衡的,但平衡性能仍是要比BST要好。其查找代價基本維持在O(logN)左右,但在最差狀況下(最長路徑是最短路徑的2倍少1),比AVL要略遜色一點。
RBT插入結點時,須要旋轉操做和變色操做。但因爲只須要保證RBT基本平衡就能夠了。所以插入結點最多隻須要2次旋轉,這一點和AVL的插入操做同樣。雖然變色操做須要O(logN),可是變色操做十分簡單,代價很小。
RBT的刪除操做代價要比AVL要好的多,刪除一個結點最多隻須要3次旋轉操做。
查找 效率最好狀況下時間複雜度爲O(logN),但在最壞狀況下比AVL要差一些,但也遠遠好於BST。
插入和刪除操做改變樹的平衡性的機率要遠遠小於AVL(RBT不是高度平衡的)。所以須要的旋轉操做的可能性要小,並且一旦須要旋轉,插入一個結點最多隻須要旋轉2次,刪除最多隻須要旋轉3次(小於AVL的刪除操做所須要的旋轉次數)。雖然變色操做的時間複雜度在O(logN),可是實際上,這種操做因爲簡單所須要的代價很小。
對於在內存中的查找結構而言,紅黑樹的效率已經很是好了(實際上不少實際應用還對RBT進行了優化)。可是若是是數據量很是大的查找呢?將這些數據所有放入內存組織成RBT結構顯然是不實際的。實際上,像OS中的文件目錄存儲,數據庫中的文件索引結構的存儲…. 都不可能在內存中創建查找結構。必須在磁盤中創建好這個結構。那麼在這個背景下,RBT仍是一種好的選擇嗎?
在磁盤中組織查找結構,從任何一個結點指向其餘結點都有可能讀取一次磁盤數據,再將數據寫入內存進行比較。你們都知道,頻繁的磁盤IO操做,效率是很低下的(機械運動比電子運動要慢不知道多少)。顯而易見,全部的二叉樹的查找結構在磁盤中都是低效的。所以,B樹很好的解決了這一個問題。
B-Tree做爲一個平衡多路查找樹(m-叉)。B樹的查找分紅兩種:一種是從一個結點查找另外一結點的地址的時候,須要定位磁盤地址(查找地址),查找代價極高。另外一種是將結點中的有序關鍵字序列放入內存,進行優化查找(能夠用折半),相比查找代價極低。而B樹的高度很小,所以在這一背景下,B樹比任何二叉結構查找樹的效率都要高不少。並且B+樹做爲B樹的變種,其查找效率更高。
B-Tree的插入會發生結點的分裂操做。當插入操做引發了s個節點的分裂時,磁盤訪問的次數爲h(讀取搜索路徑上的節點)+2s(回寫兩個分裂出的新節點)+1(回寫新的根節點或插入後沒有致使分裂的節點)。所以,所須要的磁盤訪問次數是h+2s+1,最多可達到3h+1。所以插入的代價是很大的。
B-Tree的刪除會發生結點合併操做。最壞狀況下磁盤訪問次數是3h=(找到包含被刪除元素須要h次讀訪問)+(獲取第2至h層的最相鄰兄弟須要h-1次讀訪問)+(在第3至h層的合併須要h-2次寫訪問)+(對修改過的根節點和第2層的兩個節點進行3次寫訪問)。
一顆m階(m>=3,即一個結點包含的數據和子節點數),3階B-樹有以下特色:
1. 根結點之多3顆子樹
2. 定義:
define m 3 /*B 樹的階*/
typedef struct Node{
int keynum; /* 結點中關鍵碼的個數,即結點的大小*/
int key[m]; /*結點數據數組*/
struct Node *parent; /*指向父節點的指針*/
Node*son[m]; /*指向子結點的指針數組*/
};
因爲考慮磁盤儲存結構,B樹的查找、刪除、插入的代價都遠遠要小於任何二叉結構樹(讀寫磁盤次數的下降)。
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的整體統計性能要好於平衡二叉樹。
B+樹是B-樹的一種變體,在磁盤查找結構中,B+樹更適合文件系統的磁盤存儲結構。
結構對比:
B-樹是平衡多路查找樹,全部結點中都包含了待查關鍵字的有效信息(好比文件磁盤指針)。每一個結點如有n個關鍵字,則有n+1個指向其餘結點的指針。
B+樹相比B-樹的特色:
1. 數據只出如今葉子結點,B-樹每一個結點都包含了數據;
2. 葉子結點之間用指針鏈接;
3. B+樹的高度通常是3;
查找對比:
1. 在相同數量的待查數據下,B+樹查找過程當中須要調用的磁盤IO操做要少於普通B-樹。因爲B+樹所在的磁盤存儲背景下,所以B+樹的查找性能要好於B-樹。
2. B+樹的查找效率更加穩定,由於全部葉子結點都處於同一層中,並且查找全部關鍵字都必須走完從根結點到葉子結點的所有歷程。所以同一顆B+樹中,任何關鍵字的查找比較次數都是同樣的。而B樹就不必定了,可能查找到某一個非終結點就結束了。
插入刪除對比: B+樹與B-樹在插入刪除操做中的效率是差很少的。
整體評價:在應用背景下,特別是文件結構存儲中。B+樹的應用要更多,其效率也要比B-樹好。