這個東西,保證了樹的深度很低,而且旋轉的次數很少.較同類的AVL樹有了很大的提高.但是實現起來,並不簡單.
好吧,繼續我的習慣,代碼說明問題.
/*RedBlackTree.c -- 紅/黑樹狀結構實現檔案*/<br />#include "RedBlackTree.h"</p><p>/*全域變數引用*/</p><p>extern Node * NullNode ;<br />extern Node * Current, * Sibling, * Parent, * GrParent, * GrGrParent ;</p><p>/*局部函式宣告*/</p><p>static Node * singleRotateWithLeft (Node * const parent) ;<br />static Node * singleRotateWithRight (Node * const parent) ;<br />static Node * rotate (Node * const parent, const Item item) ;<br />static void handleReorient (RedBlackTree * const prbt, const Item item) ;<br />static void changeColor (void) ;<br />static void traversal (const Node * const pn, void (* pfun) (const Node * const pn)) ;<br />static void release (Node * const pn) ;</p><p>/*介面函數定義*/</p><p>/*(*prbt) -> root -> right is the real root instead of (*prbt) -> root.*/<br />BOOL Create_R (RedBlackTree * const prbt)<br />{<br />NullNode = (Node *) malloc (sizeof (Node)) ;<br />if (NULL == NullNode)<br />return FALSE ;<br />*prbt = (struct redBlackTree *) malloc (sizeof (struct redBlackTree)) ;<br />if (NULL == *prbt)<br />{<br />free (NullNode) ;<br />NullNode = NULL ;<br />return FALSE ;<br />}<br />(*prbt) -> root = (Node *) malloc (sizeof (Node)) ;<br />if (NULL == (*prbt) -> root)<br />{<br />free (NullNode) ;<br />NullNode = NULL ;<br />free (*prbt) ;<br />}<br />NullNode -> item = INFINITY ;<br />NullNode -> left = NullNode -> right = NullNode ;<br />NullNode -> color = Black ;</p><p>(*prbt) -> root -> item = NEGATIVE_INFINITY ;<br />(*prbt) -> root -> left = (*prbt) -> root -> right = NullNode ;<br />(*prbt) -> root -> color = Black ;</p><p>(*prbt) -> current = 0 ;</p><p>return TRUE ;<br />}</p><p>BOOL IsEmpty_R (const RedBlackTree * const prbt)<br />{<br />if (0 == (*prbt) -> current)<br />return TRUE ;<br />else<br />return FALSE ;<br />}</p><p>BOOL Insert_R (RedBlackTree * const prbt, const Item item)<br />{<br />Node * newNode ;</p><p>GrParent = Parent = Current = (*prbt) -> root ;<br />NullNode -> item = item ;</p><p>while (Current -> item != item)<br />{<br />GrGrParent = GrParent ;<br />GrParent = Parent ;<br />Parent = Current ;<br />if (item < Current -> item)<br />Current = Current -> left ;<br />else<br />Current = Current -> right ;<br />if (Red == Current -> left -> color && Red == Current -> right -> color)<br />handleReorient (prbt, item) ;<br />}<br />if (Current != NullNode)<br />return FALSE ;<br />newNode = (Node *) malloc (sizeof (Node)) ;<br />if (NULL == newNode)<br />return FALSE ;<br />newNode -> item = item ;<br />newNode -> left = newNode -> right = NullNode ;</p><p>if (item < Parent -> item)<br />Parent -> left = newNode ;<br />else<br />Parent -> right = newNode ;<br />Current = newNode ;<br />handleReorient (prbt, item) ;</p><p>(*prbt) -> current++ ;</p><p>return TRUE ;<br />}</p><p>/*The central idea is go to delete a red leaf.*/<br />BOOL Delete_R (RedBlackTree * const prbt, const Item item)<br />{<br />BOOL found = FALSE ;<br />Node * record ;<br />Item scapegoat ;<br />int temp ;</p><p>if (IsEmpty_R (prbt))<br />return FALSE ;<br />Current = (*prbt) -> root ;<br />/*First, look for it.*/<br />while (Current != NullNode)<br />{<br />if (item == Current -> item)<br />{<br />found = TRUE ;<br />record = Current ;<br />break ;<br />}<br />else if (item < Current -> item)<br />{<br />Parent = Current ;<br />Current = Current -> left ;<br />}<br />else<br />{<br />Parent = Current ;<br />Current = Current -> right ;<br />}<br />}<br />/*If not found.*/<br />if (FALSE == found)<br />return FALSE ;<br />if (Current -> right != NullNode)<br />{<br />Parent = Current ;<br />Current = Parent -> right ;<br />scapegoat = Current -> item ;<br />/*Without optimizing it.*/<br />while (Current -> left != NullNode)<br />{<br />Parent = Current ;<br />Current = Current -> left ;<br />scapegoat = Current -> item ;<br />}<br />/*Make it be a lead.*/<br />if (Current -> right != NullNode)<br />{<br />temp = Current -> color ;<br />Current -> color = Current -> right -> color ;<br />Current -> right -> color = temp ;<br />Parent -> left = singleRotateWithRight (Current) ;<br />}<br />}<br />else if (Current -> left != NullNode)<br />{<br />Parent = Current ;<br />Current = Parent -> left ;<br />scapegoat = Current -> item ;<br />while (Current -> right != NullNode)<br />{<br />Parent = Current ;<br />Current = Current -> right ;<br />scapegoat = Current -> item ;<br />}<br />if (Current -> left != NullNode)<br />{<br />temp = Current -> color ;<br />Current -> color = Current -> left -> color ;<br />Current -> left -> color = temp ;<br />Parent -> right = singleRotateWithLeft (Current) ;<br />}<br />}<br />/*If Current is a leaf.*/<br />else<br />{<br />/*If current is a red leaf.*/<br />if (Red == Current -> color)<br />{<br />if (Current == Parent -> left)<br />Parent -> left = NullNode ;<br />else<br />Parent -> right = NullNode ;<br />free (Current) ;<br />(*prbt) -> current-- ;<br />return TRUE ;<br />}<br />else<br />scapegoat = Current -> item ;<br />}<br />/*Next hasn't be integrated.*/<br />(*prbt) -> root -> color = Red ;<br />Current = (*prbt) -> root ;<br />/*Make sure NullNode -> item hasn't appear in the tree.*/<br />NullNode -> item = (*prbt) -> root -> item ;<br />/*Core loop.*/<br />while (Current -> item != scapegoat)<br />{<br />if (scapegoat < Current -> item)<br />{<br />/*Updata node.*/<br />GrParent = Parent ;<br />Parent = Current ;<br />Current = Parent -> left ;<br />Sibling = Parent -> right ;<br />/*If Current has a leaf at least.*/<br />if (Red == Current -> left -> color || Red == Current -> right -> color)<br />{<br />if (scapegoat < Current -> item)<br />{<br />/*If Current drops onto a black node.*/<br />if (Black == Current -> left -> color)<br />{<br />Current -> color = Red ;<br />Current -> right -> color = Black ;<br />Parent -> left = singleRotateWithRight (Current) ;<br />}<br />/*If Current drops on to a red node, update node and continue.*/<br />else<br />{<br />GrParent = Parent ;<br />Parent = Current ;<br />Current = Parent -> left ;<br />Sibling = Parent -> right ;<br />continue ;<br />}<br />}<br />else<br />{<br />/*If Current drops onto a black node.*/<br />if (Black == Current -> right -> color)<br />{<br />Current -> color = Red ;<br />Current -> left -> color = Black ;<br />Parent -> left = singleRotateWithLeft (Current) ;<br />}<br />/*If Current drops on to a red node, update node and continue.*/<br />else<br />{<br />GrParent = Parent ;<br />Parent = Current ;<br />Current = Parent -> right ;<br />Sibling = Parent -> left ;<br />continue ;<br />}<br />}<br />}<br />/*If Current has two black children.*/<br />if (Black == Current -> left -> color && Black == Current -> right -> color)<br />{<br />/*If Sibling's left child is red.*/<br />if (Red == Sibling -> left -> color)<br />{<br />Parent -> right = singleRotateWithLeft (Sibling) ;<br />Parent -> color = Black ;<br />Current -> color = Red ;<br />if (Parent == GrParent -> left)<br />GrParent -> left = singleRotateWithRight (Parent) ;<br />else<br />GrParent -> right = singleRotateWithRight (Parent) ;<br />}<br />/*If Sibling's right child is red.*/<br />else if (Red == Sibling -> right -> color)<br />{<br />Parent -> color = Black ;<br />Sibling -> right -> color = Black ;<br />Sibling -> color = Red ;<br />Current -> color = Red ;<br />if (Parent == GrParent -> left)<br />GrParent -> left = singleRotateWithRight (Parent) ;<br />else<br />GrParent -> right = singleRotateWithRight (Parent) ;<br />}<br />/*If Sibling has two black children.*/<br />else<br />changeColor () ;<br />}<br />}<br />/*The circumstances of whirling has a little strange.*/<br />else<br />{<br />GrParent = Parent ;<br />Parent = Current ;<br />Current = Parent -> right ;<br />Sibling = Parent -> left ;<br />if (Red == Current -> left -> color || Red == Current -> right -> color)<br />{<br />if (scapegoat < Current -> item)<br />{<br />if (Black == Current -> left -> color)<br />{<br />Current -> color = Red ;<br />Current -> right -> color = Black ;<br />Parent -> right = singleRotateWithRight (Current) ;<br />}<br />else<br />{<br />GrParent = Parent ;<br />Parent = Current ;<br />Current = Parent -> left ;<br />Sibling = Parent -> right ;<br />continue ;<br />}<br />}<br />else<br />{<br />if (Black == Current -> right -> color)<br />{<br />Current -> color = Red ;<br />Current -> left -> color = Black ;<br />Parent -> left = singleRotateWithLeft (Current) ;<br />}<br />else<br />{<br />GrParent = Parent ;<br />Parent = Current ;<br />Current = Parent -> right ;<br />Sibling = Parent -> left ;<br />continue ;<br />}<br />}<br />}<br />if (Black == Current -> left -> color && Black == Current -> right -> color)<br />{<br />if (Red == Sibling -> left -> color)<br />{<br />Parent -> color = Black ;<br />Sibling -> left -> color = Black ;<br />Sibling -> color = Red ;<br />Current -> color = Red ;<br />if (Parent == GrParent -> left)<br />GrParent -> left = singleRotateWithLeft (Parent) ;<br />else<br />GrParent -> right = singleRotateWithLeft (Parent) ;<br />}<br />else if (Red == Sibling -> right -> color)<br />{<br />Parent -> left = singleRotateWithRight (Sibling) ;<br />Parent -> color = Black ;<br />Current -> color = Red ;<br />if (Parent == GrParent -> left)<br />GrParent -> left = singleRotateWithLeft (Parent) ;<br />else<br />GrParent -> right = singleRotateWithLeft (Parent) ;<br />}<br />else<br />{<br />changeColor () ;<br />if (Red == NullNode -> color)<br />{<br />putchar ('/a') ;<br />NullNode -> color = Black ;<br />}<br />}<br />}<br />}<br />}<br />/*Replace.*/<br />record -> item = scapegoat ;<br />if (scapegoat == Parent -> left -> item)<br />Parent -> left = NullNode ;<br />else<br />Parent -> right = NullNode ;<br />free (Current) ;<br />(*prbt) -> root -> color = Black ;<br />(*prbt) -> root -> right -> color = Black ;</p><p>(*prbt) -> current-- ;</p><p>return TRUE ;<br />}</p><p>void Traversal_R (const RedBlackTree * const prbt, void (* pfun) (const Node * const pn))<br />{<br />traversal ((*prbt) -> root -> right, pfun) ;<br />putchar ('/n') ;<br />}</p><p>void Release_R (const RedBlackTree * const prbt)<br />{<br />release ((*prbt) -> root -> right) ;<br />free ((*prbt) -> root) ;<br />free (*prbt) ;<br />free (NullNode) ;<br />}</p><p>/*局部函數定義*/</p><p>/*child will become the new root of the subtree.*/<br />static Node * singleRotateWithLeft (Node * const parent)<br />{<br />Node * child ;</p><p>child = parent -> left ;<br />parent -> left = child -> right ;<br />child -> right = parent ;</p><p>return child ;<br />}</p><p>static Node * singleRotateWithRight (Node * const parent)<br />{<br />Node * child ;</p><p>child = parent -> right ;<br />parent -> right = child -> left ;<br />child -> left = parent ;</p><p>return child ;<br />}</p><p>static Node * rotate (Node * const parent, const Item item)<br />{<br />if (item < parent -> item)<br />{<br />return parent -> left = item < parent -> left -> item ?<br />singleRotateWithLeft (parent -> left)<br />: singleRotateWithRight (parent -> left) ;<br />}<br />else<br />{<br />return parent -> right = item < parent -> right -> item ?<br />singleRotateWithLeft (parent -> right)<br />: singleRotateWithRight (parent -> right) ;<br />}<br />}</p><p>static void handleReorient (RedBlackTree * const prbt, const Item item)<br />{<br />Current -> color = Red ;<br />Current -> left -> color = Current -> right -> color = Black ;</p><p>if (Red == Parent -> color)<br />{<br />GrParent -> color = Red ;<br />if ((item < GrParent -> item) != (item < Parent -> item))<br />Parent = rotate (GrParent, item) ;<br />Current = rotate (GrGrParent, item) ;<br />Current -> color = Black ;<br />}<br />(*prbt) -> root -> right -> color = Black ;<br />}</p><p>/*Won't change NullNode's color.*/<br />static void changeColor (void)<br />{<br />if (Parent -> left != NullNode)<br />Parent -> left -> color = Red ;<br />Parent -> color = Black ;<br />Parent -> right -> color = Red ;<br />}</p><p>static void traversal (const Node * const pn, void (* pfun) (const Node * const pn))<br />{<br />if (pn != NullNode)<br />{<br />traversal (pn -> left, pfun) ;<br />(* pfun) (pn) ;<br />traversal (pn -> right, pfun) ;<br />}<br />}</p><p>static void release (Node * const pn)<br />{<br />if (pn != NullNode)<br />{<br />release (pn -> left) ;<br />release (pn -> right) ;<br />free (pn) ;<br />}<br />}