算法導論學習-binary search tree

1. 概念:node

Binary-search tree(BST)是一顆二叉樹,每一個樹上的節點都有<=1個父親節點,ROOT節點沒有父親節點。同時每一個樹上的節點都有[0,2]個孩子節點(left child AND right child)。每一個節點都包含有各自的KEY值以及相應的satellite data。其中KEY是幾種BST基本操做的主要操做對象。算法

 

2. BST的特別性質:函數

BST任何一顆子樹上的三個節點left, parent, right. 知足條件left.key<parent.key<=right.key,一顆典型的BST以下圖所示:spa

              

觀察以後不難發現若是對BST進行PREORDER walk(先序遍歷),獲得:2, 5, 5, 6, 7, 8 恰好是升序排列。code

P.S 所謂PREORDER walk,就是要訪問以ROOT爲根的樹,先要訪問ROOT.left, 而後訪問ROOT, 最後訪問ROOT.right。對象

用pseudocode的形式的話,就是這樣: blog

PREORDER-WALK(x) 1 if(x!=NIL) 2   PREORDER-WALK(x.left) 3   print x.key 4   PREORDER-WALK(x.right) 

 

3. BST的幾種基本操做:遞歸

SEARCH, MINIMUM, MAXIMUM, PREDECESSOR, SUCCESSOR, INSERT, and DELETE.it

2.1 SEARCH:io

TREE-SEARCH(x, k) INPUT: BST ROOT node, value k. OUPUT: node in BST whose key equals to k 1 if(x==NIL) OR (k==x.key) 2   return x 3 if(k<x.key) 4   return TREE-SEARCH(x.left, k) 5 else return TREE-SEARCH(x.right, k)

算法解釋:當咱們要找到key值爲k的節點在BST中的位置,咱們通常調用上述函數TREE-SEARCH(ROOT, k)(ROOT爲BST的根節點)。若是ROOT節點的key值等於k,則咱們要找的節點就是根節點ROOT。若是不是,根據BST的特殊性質:

left.key<parent.key<=right.key

咱們比較當前節點的key值,若是current.key<k,則要在當前節點的左子樹中查找,反之,則在右子樹中查找。[line3-line5]

 

2.2 MINIMUM:

TREE-MINIMUM(x) INPUT: BST ROOT node OUTPUT: the smallest key in BST 1 if(x==NIL) return; 2 while(x.left!=NIL) 3   x=x.left 4 return x.key

算法解釋:一個BST的最左葉子節點的key值就是BST全部key值中最小的。這個根據BST的特殊性質很容易推導出來:

由於 left.key < parent.key < parent.key < .... < root.key

有了MINIMUM算法,MAXIMUM算法也就有了:

 

2.3 MAXIMUM:

TREE-MAXIMUM(x) INPUT: BST ROOT node OUTPUT: the smallest key in BST 1 if(x==NIL) return; 2 while(x.right!=NIL) 3   x=x.right 4 return x.key

2.4 SUCCESSOR:

TREE-SUCCESSOR(x) INPUT: arbitray node x in BST OUTPUT: x's successor node 1 if(x.right!=NIL) 2   TREE-MINIMUM(x.right) 3 y=x.parent 4 while(y!=NIL AND y.left==x) 5   x=y 6   y=y.parent 7 return y

這裏說明一下SUCCESSOR的含義,x的SUCCESSOR知足x.key<=x.SUCCESSOR.key,而且x.SUCCESSOR.key是距離x.key最近的值,即x.SUCCESSOR.key是x.key的最小上限(minimum ceiling)

算法思想:由於在BST中,有x.key<=x.right.key。因此若是某BST的節點x有右孩子節點(x.right!=NIL),則利用TREE-MINIMUM在x的右子樹中查找便可。若是x不存在右孩子,則檢查x是否有父親節點而且x必須是父親節點的左孩子,只有這樣纔有parent.key>parent.left.key。但找到x的parent就結束了嗎,尚未,就像TREE-MINIMUM函數同樣,咱們須要逐層查找,當找到符合條件的parent後,咱們遞歸的繼續檢查parent節點有沒有parent.parent節點符不符合上述條件。知道訪問到的parent節點不符合該條件爲止

 

2.5 INSERT:

TREE-INSERT(T, z) 1 y=NIL 2 x=T.ROOT 3 while(x!=NIL) 4   y=x 5   if(z.key<x.key) 6     x=x.left 7   else x=x.right 8 z.p=y 9 if(y==NIL) T.ROOT=z 10 if(z.key<y.key) y.left=z 11 else y.right=z

用一張圖來解釋該算法:

   

虛線指向的key值爲13的節點是即將要插入BST的點,其餘的點已經在BST上。能夠看到從ROOT節點出發,根據「左小右大」規則,咱們很快找到了key值爲15的節點,由於13<15,因此檢查‘15’節點是否有左孩子,結果是沒有,因此把13放到15的左孩子節點處。咱們能夠想象若是要插入的節點key是16會怎麼樣?一樣的,咱們仍是找到‘15’節點,可是16>15,因此繼續往‘右’查找,找到‘17’,由於16<17,看17有沒有左孩子節點,沒有,因此會把‘16’放到‘17’的左孩子節點處。

2.6 TRANSPLANT:

 

TRANPLANT(T, u, v) 1 if (u.parent==NIL) T.ROOT=v 2 else if(u==u.parent;.left) u.parent.left=v 3 else u.parent.right=v 4 if(v!=NIL) v.parent=u.parent

 仍是用一張圖來展現比較清晰:

2.7 DELETE:

TREE-DELETE(T, z) 1 if z.left==NIL 2 TRANSPLANT(T, z, z.right) 3 else if z.right == NIL 4 TRANSPLANT(T, z, z.left) 5 else y=TREE-MINIMUM(z.right) 6 if y.parent!=z 7 TRANSPLANT(T, y, y.right) 8 y.right=z.right 9 y.right.parent=y 10 TRANSPLANT(T, z, y) 11 y.left=z.left 12 y.left.parent=y 

 DELETE算法相對來講比較麻煩一些,須要考慮的狀況要多一些。由於要在刪除BST的某一節點後仍能維持BST的基本性質。假設要刪除的節點是z,z的key值爲k。根據「左小右大」原則,z.left.key<k<=z.right.key.若是這時候吧z刪了,誰來接替z的位置呢而且保證解體以後的新BST知足性質呢?方法咱們能夠根據性質來推導:咱們要找到一個除了z之外的節點在BST中,該節點假設爲P,那麼P.key要大於z.left.key而且P.key>=z.right.key,實際上很明顯的,惟一符合要求的就是z的SUCCESSOR。

若是z只有左子樹或者只有右子樹,那麼問題就很簡單,使z的左孩子或者右孩子來頂替z的位置便可。若是z的左子樹和右子樹都存在,那麼問題稍微複雜一點,咱們要在BST上找到z的SUCCESSOR。如此一來,這個問題又變成咱們以前討論的SUCCESSOR問題了,總共有兩種情形:

第一種情形:z的右孩子就是咱們要找的z的SUCCESSOR,那咱們就直接TRANSPLANT移植以z.right爲根的子樹到z的位置中去。

第二種情形:z的右孩子不是咱們要找的z的SUCCESSOR,那咱們就從z.right出發,‘深刻’尋找知道找到z的SUCCESSOR,假設爲Q。

那麼咱們讓Q成爲z.right的父親節點,而且讓以Q爲根的右子樹(由於是根據「最左原則」找到的Q,Q要麼是以z.right爲根的left-most葉子節點,要麼Q只有右子樹。)取代Q的位置。最後讓Q取代z的位置。。。很繞。。。仍是見圖吧。

   

相關文章
相關標籤/搜索