樹旋轉

樹旋轉是在二叉樹中的一種子樹調整操作, 每一次旋轉並不影響對該二叉樹進行中序遍歷的結果。 樹旋轉通常套用於需要調整樹的局部平衡性的場合。樹旋轉包括兩個不同的方式,分別是。 兩種旋轉呈鏡像,而且互為逆操作。

實現

假設從樹中任一節點 N 能夠藉由 N.left 訪問其左子節點, N.right 訪問其右子節點, N.parent 訪問其父節點. 此外, 稱旋轉後變為父親的節點為轉軸 pivot, 稱 pivot 在旋轉前的父節點為 parent, 而 parent 在旋轉前的父節點為 root. 則右旋轉過程可用偽代碼表示為

func rotate_right(pivot):

let parent = pivot.parent

let root = parent.parent

// R0

parent.left = pivot.right

if pivot.right != nil:

pivot.right.parent = parent

// R1

pivot.parent = root

if parent == root.left:

root.left = pivot

else:

root.right = pivot

pivot.right = parent

parent.parent = pivot

而左旋轉可表示為

func rotate_left(pivot):

let parent = pivot.parent

let root = parent.parent

// L0

parent.right = pivot.left

if pivot.left != nil:

pivot.left.parent = parent

// L1 pivot.parent = root

if parent == root.left:

root.left = pivot

else:

root.right = pivot

pivot.left = parent

parent.parent = pivot

上述過程並不適用於當 parent 節點本身就是樹的根節點的情況。這種情況下, 需要以其它方式重設樹的根節點為 pivot。一種無需在根節點的某一子節點為轉軸時進行特殊處理的替代方案是讓樹的實際的根節點是一個特殊入口節點,而邏輯上的根節點作為該入口節點的某個子節點存在, 並避免任何以邏輯根節點為轉軸的旋轉。

如果從節點出發, 只能訪問其兩個子節點, 而無法訪問其父節點,那么上述方法也不適用。 這種情況下, root 節點亦是旋轉的必要參數之一。旋轉過程的偽代碼表示如下

func rotate_right(root, parent):

assert root.left == parent || root.right == parent

let pivot = parent.left

// R0

parent.left = pivot.right

// R1

if parent == root.left:

root.left = pivot

else:

root.right = pivot

pivot.right = parent

func rotate_left(root, parent):

assert root.left == parent || root.right == parent

let pivot = parent.right

// L0

parent.right = pivot.left

// L1

if parent == root.left:

root.left = pivot

else:

root.right = pivot

pivot.left = parent

旋轉距離

兩棵二叉樹之間的旋轉距離指的是,其中一棵樹通過儘可能少的樹旋轉變換到另一棵樹, 此過程中所使用的旋轉次數。對於一個包含相同個數節點的二叉樹集合,它們兩兩之間的距離可以構成一個度量空間。 是否存在一個算法, 能在多項式時間內計算兩個二叉樹之間的旋轉距離,目前還是一個未決問。

相關詞條

相關搜尋

熱門詞條

聯絡我們