void rbInsert(NODE *z) { NODE *y = nil; NODE *x = root; while (x != nil) { y = x; if (z->key < x->key) { x = x->l; } else { x = x->r; } } z->p = y; if (y == nil) { root = z; } else { if (z->key < y->key) { y->l = z; } else { y->r = z; } } z->l = nil; z->r = nil; z->c = RED; rbInsertFixup(z); } void rbInsertFixup(NODE *z) { NODE *y; while (z->p->c == RED) { if (z->p == z->p->p->l) {// z 的父親是爺爺的左兒子 y = z->p->p->r;// z 的叔叔 y if (y->c == RED) {// case 1:叔叔是紅的 z->p->c = BLACK;// 將 z 的父親與叔叔置爲黑 y->c = BLACK; z->p->p->c = RED;// 將 z 的爺爺置爲紅 z = z->p->p;// 問題上移兩層 } else { if (z == z->p->r) {// case 2:z 是右兒子 z = z->p; leftRotate(z);// 左旋,轉爲 case 3 } z->p->c = BLACK;// case 3:z 是左兒子,對z的爺爺作一次右旋便可完成維護 z->p->p->c = RED; rightRotate(z->p->p); } } else if (z->p == z->p->p->r) {// z 的父親是爺爺的右兒子 y = z->p->p->l;// z 的叔叔 y if (y->c == RED) {// case 1:叔叔是紅的 z->p->c = BLACK;// 將 z 的父親與叔叔置爲黑 y->c = BLACK; z->p->p->c = RED;// 將 z 的爺爺置爲紅 z = z->p->p;// 問題上移兩層 } else { if (z == z->p->l) {// case 2:z 是左兒子 z = z->p; rightRotate(z);// 右旋,轉爲 case 3 } z->p->c = BLACK; z->p->p->c = RED; leftRotate(z->p->p); } } } root->c = BLACK; }
13.3-1 RB-INSERT中假設新插入的節點是紅的。注意若是將z着爲黑色,則紅黑樹的性質4)就不會被破壞。那麼咱們爲何沒有選擇將z着爲黑色呢?指針
性質5)被破壞。code
13.3-2 在將關鍵字41,38,31,12,19,8插入一棵初始爲空的紅黑樹中以後結果樹是什麼樣子?blog
13.3-3 假設3種情景中子樹αβγδε的黑高度都是k。標上各個結點的黑高度,以驗證圖中所示的各類轉換能保證性質5)。ip
case 1:皆爲kclass
case 2:皆爲kfile
case 3:皆爲kim
13.3-4 證實RB-INSERT-FIXUP永遠不會將nil的COLOR設置爲RED。img
case 1:將z的爺爺置爲紅,考慮z的爺爺爲nil的狀況,則z爲root的兒子,而在該狀況下,root不是nil的兒子,所以不會進入任何case中。紅黑樹
case 二、3:對z的爺爺作一次右旋並染爲紅,若z的爺爺爲nil,與case 1一樣的緣由,不會出現這種狀況。while
綜上,nil永遠不會被設置爲RED。
13.3-5 考慮用RB-INSERT插入n個結點而成的一棵紅黑樹。證實:若是n>1,則該樹至少有一個紅結點。
當n==2時,不進行維護,該樹有一個紅葉子結點。
假設n==k-1時,至少有一個紅結點。
當n==k時,case 1中,一黑三紅變爲兩黑兩紅,至少有兩個紅結點;case 2與case 3中,兩紅一黑結點數量不變。如有紅的根結點被染爲黑,仍然剩下至少一個紅結點。
所以n>1時該樹至少一個紅結點。
13.3-6 說明若是紅黑樹的表示中不提供父指針的話,應當如何有效的實現RB-INSERT。