這一篇解決《演算法導論》中紅/黑樹狀結構章節的部分習題,在上一篇自己親自實現紅/黑樹狀結構後,解決這些題目就輕鬆多了。
練習13.1-6 在一棵黑高度為 $k$ 的紅/黑樹狀結構中,內節點最多有多少個?最少有多少個?
黑高度為 $k$ 的二叉樹,全高度最小為 $k+1$,最大為 $2k+2$ 。內節點最多有 $2^{k+1}-1$ 個,這種情況下紅/黑樹狀結構中沒有紅節點,黑節點全滿(滿足所有葉子節點黑高度一致的條件);內節點最多有 $2^{2k+2}-1=4^{k+1}-1$ 個。這種情況下紅/黑樹狀結構全滿。
練習13.1-7 在 $n$ 個關鍵字上構造出來的二叉樹,紅節點與黑節點個數的比值最大為多少?最小是多少?
紅節點最多時,比值為:
$$\frac{n-2^{h-1}-2^{h-3}-...-(2)-1}{2^{h-1}+2^{h-3}+...+(2)+1},h=\lfloor\lg n\rfloor$$
紅節點最少時,比值時為:
$$\frac{n-2^{\lfloor\lg n\rfloor}}{2^{\lfloor\lg n\rfloor}}$$
練習13.2-2 證明,在一棵 $n$ 個節點的二叉尋找樹中,剛好有 $n-1$ 種可能的旋轉。
思路:每一個可能的旋轉對應於一條邊,每一個條邊也只能對應一個可能的旋轉,因此可能的旋轉數就是邊的數目。每一條邊都對應一個兒子節點,每一個節點(除了根節點)都對應一個邊,所以邊的數目為 $n-1$ ,也就是可能的旋轉的數目。
練習13.2-4 證明任意一顆含有 $n$ 個節點的二叉尋找樹都能通過 $O(n)$ 次旋轉,轉變為另一顆含有同樣節點(節點位置可以任意不一樣,但仍然保持二叉尋找樹性質)的二叉尋找樹。
思路:考慮一顆二叉尋找樹的“右鏈”,即從根節點向具有最大節點值的節點的路徑。不斷地右旋右鏈上具有左子樹的節點,每一次旋轉可以使右鏈上多一個節點,(又,右鏈上至少有一個節點,根節點),所以至多 $n-1$ 次右旋後,二叉樹的右鏈上串連了所有的節點,這時二叉樹實際上稱了一個已排序(旋轉保持二叉尋找樹的性質)的單鏈表。旋轉是可逆的,所以任意兩棵二叉尋找樹都可以通過至多 $2n-2=O(n)$ 次旋轉來互相變換。
練習13.4-7 假設用 RB-INSERT 方法將一個節點 $x$ 插入到紅/黑樹狀結構中,再用 RB-DELETE 方法刪除之,請問結果的紅/黑樹狀結構與初始的紅/黑樹狀結構是否一致?答:不一致。
思考題13-1 持久動態集合。持久動態集合是這樣的集合,每當集合被更新(插入元素或刪除元素)時,仍然需要維護該集合的一個較舊的版本。比如就展示了一個二叉尋找樹的持久動態集合,對於每個版本,都會有一個對應的根節點,所有根節點處在一個可維護的鏈表中,可以通過該鏈表訪問所有的根節點,進而訪問所有的版本。該二叉樹節點沒有父節點域。
- 對一個持久二叉尋找樹,插入或刪除一個關鍵字 $z$ 的,需要改變哪些節點?答:不需要改變任何節點,只需要新增從根節點開始到插入/刪除節點路徑上的所有節點。
- 寫出向持久二叉尋找樹中插入一個節點的過程
PERSISTENT-TREE-INSERT(T, node) tmpO = T.head; tmpN = copy(tmpO); headN = tmpN; if(tmpO = NULL) headN = node; return headN; while(true) if(node.key <= tmpO.key) if(tmpO->left isNot NULL) tmpN->left = copy(tmpO->left); tmpO = tmpO->left; tmpN = tmpN->left; else // tmpO->left is NULL tmpN->left = node; break; else if(tmpO->right isNot NULL) tmpN->right = copy(tmpO->right); tmpO = tmpO->right; tmpN = tmpN->right; else // tmpO->right is NULL tmpN->right = node; break; return headN;
- 如果持久二叉尋找樹的高度為 $h$ ,則實現上述過程的時間空間要求是多少?答:$O(h)$ 和 $O(h)$ 。
- 假設每個節點中具有父節點域,又如何?答:每次更新二叉樹都要複製整個二叉樹了。
思考題13-2 紅/黑樹狀結構上的串連操作。串連操作將兩個動態集合 $S_{1}$、$S_{2}$ 和元素 $x$ 串連成一個動態集合,且 $S_{1}$ 中的所有元素小於 $x$,$S_{2}$ 中的所有元素大於 $x$ 。
- 給定一棵紅/黑樹狀結構,其黑高度被單獨維護在域 $bh[T]$ 中,證明在紅/黑樹狀結構的插入和刪除操作中,每一次更新 $bh[T]$ 只需要$O(1)$的時間。
思路:不論是刪除節點導致樹的黑高度降低還是增加節點導致樹的黑高度升高,這種情況都是不常見的,只有在fix操作遞迴到根節點時才需要這樣做。
- 紅/黑樹狀結構上的實現 RB-JOIN(T1, T2, x) 操作。假設 $bh[T_{1}]\geq bh[T_{2}]$,描述一個 $O(\lg n)$ 的演算法找出黑高度為 $bh[T_{2}]$ 的節點的具有最大尋找字的節點。
思路:實在太簡單了,沿著右鏈走就行了。
- $T_{y}$ 是以 $y$ 為根節點的子樹,如何在 $O(1)$ 的時間裡完成 $T_{y}\bigcup \{x\}\bigcup T_{2}$ 。
思路:$x$ 為根節點,$T_{y}$ 和 $T_{2}$ 分別為左右子樹,該樹滿足二叉尋找樹的性質。該樹替代原先的 $T_{y}$ 作為 $T_{1}$ 的子樹。
- 保持紅/黑樹狀結構性質1、3、5,則 $x$ 染成什麼顏色?如何恢複?
答:紅色,按照紅/黑樹狀結構中插入新元素後的fixInsert(x)方法恢複性質2、4。
- 對稱的情況,略。
- 已耗用時間自然是 $O(\lg n)$,更是自然。這本書的題目,只要理解了題目的意圖,其實還是比較容易。
思考題13-3 AVL樹。AVL樹是一種高度平衡的二叉樹,任意一個節點的左子樹和右子樹高度差不大於1。
思考題13-4 Treap(樹堆)。一種即具有二叉尋找樹性質,又具有堆性質的資料結構,用來類比隨機順序插入的二叉樹。每個節點有兩個域:關鍵字域與優先順序域。關鍵字域滿足二叉樹條件,優先順序域滿足最小堆條件。
- 證明對於給定的了互異關鍵字和互異優先順序的 $n$ 個元素,存在唯一的treap與之對應(二叉樹和最小堆顯然不是)。
思路:根據最小堆性質,根節點是確定的,即優先順序最小的元素;根節點確定後,實際上根據二叉樹性質將剩下的 $n-1$ 個元素分為了兩部分,大於根節點的和小於根節點,這兩部分的根節點又是確定的。如此遞迴下去,整個treap是唯一的。
- 解釋treap-insert的工作方式。
思路:先根據二叉尋找樹的插入方法插入元素,通過與父節點之間的旋轉(如果元素時左節點,就右旋,反之)將優先順序大於該元素的節點轉到下面去:首先,旋轉操作不會違背二叉尋找樹的性質;而旋轉後,以該元素為根的子樹也保留了最小堆性質。
- treap-insert操作後,被插入元素 $x$ 處在了一個新的位置,其左子樹的右鏈長度為 $C$ ,右子樹的左鏈長度為 $D$ ,求證插入 $x$ 的過程中執行了$C+D$ 次旋轉。
思路:C為左旋次數,D為右旋次數,注意右鏈的長度指右鏈上節點的長度,而不是邊的長度。
這一題後面還有幾問關於這種資料結構插入時間的期望的,就沒再繼續做了。