算法導論(九)--二叉樹

二叉搜索樹

(BST,Binary Search Tree,也叫二叉排序樹,Binary Sort Tree)

BST Sort

二叉搜索樹的定義就不講了。我們看看BST Sort,如何利用二叉樹進行排序?答案是隻要把數組構建出一棵二叉搜索樹,然後中序遍歷就行了。
構建二叉搜索樹的算法:

T<-Ø
for i<-i to n
	do Tree_Insert_Walk(T,A[i])
InOrder-Tree(T->root)

舉例:
數組A={3,1,8,2,6,7,5},構造二叉搜索樹,然後中序遍歷依次打印出來。
在這裏插入圖片描述
分析這個算法的複雜度。遍歷需要O(n)。

如果構造的是下面這樣的完全平衡的二叉樹,那麼n次插入需要Ω(nlog),因爲每次插入都需要查找,所有節點的深度加起來就是總的查詢時間,看最底層有n/2個節點,每個節點的深度都是logn,所以是至少是O(nlogn)。
在這裏插入圖片描述
如果數組已經是有序的了,那麼就會構造出下面這樣的樹,總的花費時間還是樹中每個節點深度的總和,就是1+2+3+…,等差級數,就是Θ(n2)。
在這裏插入圖片描述

與快排的關係

簡單快排
這個算法跟快排很類似,它們其實做的是相同的比較,只是比較的順序不一樣。對數組A={3,1,8,2,6,7,5}做最簡單的快排,先不改變兩邊元素的順序,過程如下圖所示:
在這裏插入圖片描述
我們通過劃分得到的樹與上面得到的二叉搜索樹其實就是同一棵樹。

Randomized BST Sort
如果是隨機的二叉搜索樹,就和隨機的快排是一樣的了。
首先隨機打亂數組的序列,然後調用BST排序。
然後隨機化的快排和隨機化的BST做的就是相同的比較了,所以它們的複雜度是一樣的,都是nlogn。

一棵隨機化的二叉搜索樹,高度的期望值是logn。

平衡搜索樹

平衡搜索樹(Balanced Search Tree)是這樣的一種數據結構,它維護一個n個元素的動態集,複雜度是logn階的,所以樹高爲O(logn)。平衡搜索樹不一定是二叉樹。

平衡搜索樹主要有以下幾種:

  • AVL樹(二叉的)
  • 2-3樹
  • 2-3-4樹
  • B樹
  • 紅黑樹(二叉的)
  • 跳躍表(不是樹,但多少有一些樹的結構)
  • 樹堆

這裏主要講紅黑樹

紅黑樹

性質

紅黑樹是一種平衡搜索樹,它能保證樹高是logn級的,所有的操作都能在logn的時間完成。紅黑樹也是二叉搜索樹的一種。紅黑樹每個節點都有一個色域,滿足紅黑性,有4個性質:

  1. 每個節點要麼是紅色,要麼是黑色
  2. 根節點和葉節點(nil)都是黑色的。葉節點是最後的內部節點的空指針,這樣每個內部節點都有兩個子節點,每個葉子節點有0個子節點。
    在這裏插入圖片描述
  3. 每個紅色節點的父節點都是黑色的。也就是說,如果觀察樹的任意路徑,不可能找到兩個連續的紅色節點,只能找到紅黑相間的或者是幾個連續的黑節點,也可以得出,最多隻有一半的節點是紅色的。
    在這裏插入圖片描述
  4. 如果選擇一條簡單路徑(不重複任何節點),從一個節點x一直到x的子孫葉節點,所有到各子孫葉節點的路徑都有相等的黑節點數。也就是所有路徑的“黑高度”都是相等的。計算“黑高度”時不包括x本身。
    在這裏插入圖片描述

舉例:
看看下面這棵紅黑樹每個節點的黑高度是多少。所有的葉節點黑高度都是0,其它節點的黑高度都標在圖上了。
在這裏插入圖片描述
創建一棵紅黑樹並不難,最簡單的可以一開始創建一個所有節點都是黑色的平衡二叉樹。問題當插入和刪除之後如何保持紅黑性。

首先要證明這些性質能推導出樹高爲O(logn)的結論。

定理:有n個鍵的紅黑樹的高度h≤2log(n+1),也就是O(logn)。(只計算內部節點)

證明:
首先要將樹做一個改造,把每個紅節點跟它的父節點合併起來,變成下面這個圖:
在這裏插入圖片描述
每個內部節點都有2~4個子節點,並且每個葉節點的深度一致,都等於根節點的黑高度。

假設原樹的高度是h,改造後的樹高度是h’,鍵數爲n。
那麼這棵樹有n+1個葉節點(一棵平衡二叉樹的葉節點樹等於內部節點數+1),一棵2-3-4樹的葉節點數 2h’≤ #leaves ≤4h’,因此 2h’ ≤ n+1,h’ ≤ log(n+1),葉節點數越多,高度會降低。
之前我們知道,一條路徑上的紅節點數最多是路徑長的一半,所有路徑裏最長的就是樹的高度,所以h’至少是h的一半,h’ ≥ 1/2·h,即h ≤ 2h’,因此h≤2log(n+1)。

紅黑樹上的操作

對於查詢:
只要紅黑樹的樹高是O(logn),那麼紅黑樹的查詢時間就是O(logn)。
對於插入和刪除:
爲了保持樹的紅黑性,有三種操作:

  1. BST操作
  2. 改變新節點顏色,並且爲周邊的節點重新着色
  3. 節點重新排列,改變指針(via rotations)

Rotation:
下圖畫的是樹的一部分,三角形表示子樹,圓形表示節點。

下面這個例子,從左往右是右旋B,右旋就是把節點A和B之間的這條邊旋轉90度,B的父節點變成了A的父節點,A變成B的新的父節點,子樹也重新排序,α還是A的子樹,γ還是B的子樹,而β由A的子樹變成了B的子樹。
同理,從右往左就是左旋A。
在這裏插入圖片描述
這個操作保持了二叉搜索樹的性質,即節點左子樹的值都小於等於該節點,右子樹的值都大於等於該節點。

旋轉操作只花費常數級的時間,因爲指針的改變是常數級的。

RB_Insert(X)
在紅黑樹中插入一個節點X。
基本思路:

  • 在BST中插入一個節點X,Tree_Insert(X)
  • 給這個節點定爲紅色。這樣可以滿足性質4,但如果它的父節點是紅色,就不滿足性質3 。
  • 如何彌補性質3?把對性質3的破壞往上移。從節點X開始往根節點重新着色,直到某個點再改用旋轉來彌補,可能還需要重新着色。

舉例:
還是對上面的紅黑樹,插入15 。15應該在11度右節點的位置。如下圖所示:
在這裏插入圖片描述
但違反了性質3,現在從根節點到葉的一條路徑上出現了兩個連續的紅節點。於是需要重新着色。如下圖所示,節點10變成紅色,8和11變成黑色。如下圖:
在這裏插入圖片描述
現在,10和18不滿足性質3了。不能再重新着色了,不能讓3變紅,7變黑,因爲根節點必須是黑色。因此我們進行旋轉。把18右旋轉,如下圖:
在這裏插入圖片描述
現在這棵樹不平衡了,還需要旋轉。左旋7,10變爲根節點。根節點必須是黑色,所以10變成黑色,7要變成紅色,如下圖:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章