1. 程式人生 > >二叉查詢樹(BST) | 平衡二叉查詢樹(AVL) | 紅黑樹(RBT)

二叉查詢樹(BST) | 平衡二叉查詢樹(AVL) | 紅黑樹(RBT)

二叉查詢樹(BST)
特點:對任意節點而言,左子樹(若存在)的值總是小於本身,而右子(若存在)的值總是大於本身。
查詢:從根開始,小的往左找,大的往右找,不大不小的就是這個節點了;
插入:從根開始,小的往左,大的往右,直到葉子,就插入,
時間複雜度期望為Ο(logn);
刪除:如果是葉子節點,直接刪除;如果不是,則去找這個節點左子樹的最大值,與之交換;如果交換後還不是葉子節點就繼續找做字數的最大值,重複操作至成為葉子節點,刪除;
左子樹如果不存在就去找右子樹的最小節點,交換,重複操作,與上同理;

平衡二叉查詢樹(AVL)
二叉查詢樹中的Ο(logn),是個期望值,如果出現比較差的情況,比如根節點為1,後依次插入2、3、4、5、6、7、8、9.。。。。那麼,資料結構上來說,樹就退化為連結串列了,但概念上還是二叉查詢樹,那麼操作的時間複雜度也就變為了O(n),導致的原因為樹不平衡,不對稱;
概念:
左高 = 左節點空 ? 0 : (左節點高+1)
右高 = 右節點空 ? 0 : (右節點高+1)
AVL的定義為:ABS(左高 - 右高) <= 1;(ABS求絕對值):即任意節點的左右高的絕對值之差為0/1;

如何是二叉查詢樹在新增資料的同時保持平衡?

基本思想就是:當在二叉排序樹中插入一個節點時,首先檢查是否因插入而破壞了平衡,若 破壞,則找出其中的最小不平衡二叉樹,在保持二叉排序樹特性的情況下,調整最小不平衡子樹中節點之間的關係,以達 到新的平衡。所謂最小不平衡子樹 指離插入節點最近且以平衡因子的絕對值大於1的節點作為根的子樹。

平衡二叉樹的新增
LL型:X節點的左高本來就大,插入點還在左子樹的左子樹上;
這裡寫圖片描述
直接以X的左子樹根節點為中心向右旋轉;
RR型:X節點的右高本來就大,插入點還在右子樹的右子樹上;
這裡寫圖片描述
直接以X的右子樹根節點為中心向左旋轉;
LR型:以上同理不贅述
這裡寫圖片描述


先將左子樹左旋轉,再整體右旋轉;
RL型:
這裡寫圖片描述
先將右子樹右旋轉,再整體左旋轉;
平衡二叉樹的刪除:
從平衡二叉樹中刪除節點更為複雜。首先第一步需要找到要刪除的節點x,並分情況進行處理:

如果要刪除的節點為葉子節點,就找到了要刪除的節點
如果要刪除的節點為只有一棵子樹的節點就找到了要刪除的節點
如果要刪除的節點既有左子樹,又有右子樹。。。
與二叉查詢樹同理:
如果是葉子節點,直接刪除;如果不是,則去找這個節點左子樹的最大值,與之交換;如果交換後還不是葉子節點就繼續找做字數的最大值,重複操作至成為葉子節點,刪除;
左子樹如果不存在就去找右子樹的最小節點,交換,重複操作,與上同理;
然後判斷是否破壞了平衡二叉樹的平衡;
關鍵點在於調整過程:
類似於插入,不過也有區別;
以從節點X的左子樹刪除節點導致其左子樹高度降低而需要調整為例進行分析:
刪除的左子樹,要調整,影響的是右子樹,所以要看右子樹的狀態;
X的右子樹的平衡因子為-1;


這裡寫圖片描述
以X為軸,直接進行左旋操作;
X的右子樹的平衡因子為0;
這裡寫圖片描述
以X為軸,直接進行左旋操作;
X的右子樹的平衡因子為1;
這裡寫圖片描述
先將X的右子樹右旋,再以X為軸左旋;

平衡二叉樹效能分析
平衡二叉樹的效能優勢:很顯然,平衡二叉樹的優勢在於不會出現普通二叉查詢樹的最差情況。其查詢的時間複雜度為O(logN)。
平衡二叉樹的缺陷:
(1) 很遺憾的是,為了保證高度平衡,動態插入和刪除的代價也隨之增加。
(2) 所有二叉查詢樹結構的查詢代價都與樹高是緊密相關的,能否通過減少樹高來進一步降低查詢代價呢。我們可以通過多路查詢樹的結構來做到這一點。
(3) 在大資料量查詢環境下(比如說系統磁盤裡的檔案目錄,資料庫中的記錄查詢 等),所有的二叉查詢樹結構(BST、AVL、RBT)都不合適。如此大規模的資料量(幾G資料),全部組織成平衡二叉樹放在記憶體中是不可能做到的。那麼把這棵樹放在磁碟中吧。問題就來了:假如構造的平衡二叉樹深度有1W層。那麼從根節點出發到葉子節點很可能就需要1W次的硬碟IO讀寫。大家都知道,硬碟的機械部件讀寫資料的速度遠遠趕不上純電子媒體的記憶體。 查詢效率在IO讀寫過程中將會付出巨大的代價。在大規模資料查詢這樣一個實際應用背景下,平衡二叉樹的效率就很成問題了。
紅黑樹(Red-Black Tree ( RBT))
紅黑樹實際上是AVL的一種變形,但是其比AVL(平衡二叉搜尋樹)具有更高的插入效率,當然查詢效率會平衡二叉樹稍微低一點點,畢竟平衡二叉樹太完美了。但是這種查詢效率的損失是非常值得的。它的操作有著良好的最壞情況執行時間,並且在實踐中是高效的: 它可以在O(log n)時間內做查詢,插入和刪除,這裡的n是樹中元素的數目。
性質1 節點是紅色或黑色。
性質2 根節點是黑色。
性質3 每個葉節點(NIL節點,空節點)是黑色的。
性質4 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
性質5 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。
這些約束的好處是:保持了樹的相對平衡,同時又比AVL的插入刪除操作的複雜性要低許多。

注意的點:

紅黑樹和AVL樹的區別在於它使用顏色來標識結點的高度,它所追求的是區域性平衡而不是AVL樹中的非常嚴格的平衡

紅黑樹和平衡二叉樹區別如下:
1、紅黑樹放棄了追求完全平衡,追求大致平衡,在與平衡二叉樹的時間複雜度相差不大的情況下,保證每次插入最多隻需要三次旋轉就能達到平衡,實現起來也更為簡單。
2、平衡二叉樹追求絕對平衡,條件比較苛刻,實現起來比較麻煩,每次插入新節點之後需要旋轉的次數不能預知。

最小二叉平衡樹的節點的公式如下 F(n)=F(n-1)+F(n-2)+1 這個類似於一個遞迴的數列,可以參考Fibonacci數列,1是根節點,F(n-1)是左子樹的節點數量,F(n-2)是右子樹的節點數量。