2 #include "redblacktree.h"
4 /* The constants below must be defined in the file which includes
5 the redblacktree.c code. */
9 #define ROOT Root /* The name of the root variable */
10 #define RBNODE struct RBTreeNode /* The name of the structure containing the left,
11 right, parent, nodecolor & data fields. */
12 #define SENTINEL Sentinel /* The name of the sentinel node variable (must be a RBNODE) */
13 #define DATA data /* The name of the data field (example: data, sub.mydata) */
15 #define CompLT(a,b) (a < b) /* modify these lines to establish data type */
16 #define CompEQ(a,b) (a == b)
21 /* Example RBTreeNode structure:
24 struct RBTreeNode *left;
25 struct RBTreeNode *right;
26 struct RBTreeNode *parent;
36 void InsertNode(RBNODE
*X
);
37 static void DeleteNode(RBNODE
*X
);
38 void InsertFixup(RBNODE
*X
);
39 static void DeleteFixup(RBNODE
*X
);
40 void RotateLeft(RBNODE
*X
);
41 void RotateRight(RBNODE
*X
);
42 RBNODE
*FindNode(unsigned long data
);
45 #define NIL &SENTINEL /* all leafs are sentinels */
46 RBNODE Sentinel
= { NULL
, NULL
, 0, BLACK
, 0};
48 RBNODE
*Root
= NULL
; /* root of red-black tree */
53 void InitRedBlackTree(void) {
55 SENTINEL
.left
=&SENTINEL
;
56 SENTINEL
.right
=&SENTINEL
;
59 // SENTINEL.magicvalue=0x4a4f;
65 void InsertNode(RBNODE
*X
) {
66 RBNODE
*current
, *parent
;
68 /***********************************************
69 * allocate node for Data and insert in tree *
70 ***********************************************/
72 /* find where node belongs */
75 while (current
!= &SENTINEL
) {
76 // if(CompEQ(X->DATA, current->DATA)) return (current);
78 current
= CompLT(X
->DATA
, current
->DATA
) ? current
->left
: current
->right
;
86 /* insert node in tree */
88 if(CompLT(X
->DATA
, parent
->DATA
)) {
104 void InsertFixup(RBNODE
*X
) {
106 /*************************************
107 * maintain red-black tree balance *
108 * after inserting node X *
109 *************************************/
111 /* check red-black properties */
112 while (X
!= ROOT
&& X
->parent
->color
== RED
) {
113 /* we have a violation */
114 if(X
->parent
== X
->parent
->parent
->left
) {
115 RBNODE
*Y
= X
->parent
->parent
->right
;
116 if(Y
->color
== RED
) {
118 X
->parent
->color
= BLACK
;
120 X
->parent
->parent
->color
= RED
;
121 X
= X
->parent
->parent
;
125 if(X
== X
->parent
->right
) {
126 /* make X a left child */
131 /* recolor and rotate */
132 X
->parent
->color
= BLACK
;
133 X
->parent
->parent
->color
= RED
;
134 RotateRight(X
->parent
->parent
);
138 /* mirror image of above code */
139 RBNODE
*Y
= X
->parent
->parent
->left
;
140 if(Y
->color
== RED
) {
143 X
->parent
->color
= BLACK
;
145 X
->parent
->parent
->color
= RED
;
146 X
= X
->parent
->parent
;
150 if(X
== X
->parent
->left
) {
154 X
->parent
->color
= BLACK
;
155 X
->parent
->parent
->color
= RED
;
156 RotateLeft(X
->parent
->parent
);
163 void RotateLeft(RBNODE
*X
) {
165 /**************************
166 * rotate Node X to left *
167 **************************/
169 RBNODE
*Y
= X
->right
;
171 /* establish X->right link */
173 if(Y
->left
!= &SENTINEL
) {
177 /* establish Y->parent link */
179 Y
->parent
= X
->parent
;
182 if(X
== X
->parent
->left
) {
186 X
->parent
->right
= Y
;
200 void RotateRight(RBNODE
*X
) {
202 /****************************
203 * rotate Node X to right *
204 ****************************/
208 /* establish X->left link */
210 if(Y
->right
!= &SENTINEL
) {
211 Y
->right
->parent
= X
;
214 /* establish Y->parent link */
216 Y
->parent
= X
->parent
;
219 if(X
== X
->parent
->right
) {
220 X
->parent
->right
= Y
;
237 static void DeleteNode(RBNODE
*Z
) {
241 /*****************************
242 * delete node Z from tree *
243 *****************************/
245 if(!Z
|| Z
== &SENTINEL
) {
249 if(Z
->left
== &SENTINEL
|| Z
->right
== &SENTINEL
) {
250 /* Y has a &SENTINEL node as a child */
254 /* find tree successor with a &SENTINEL node as a child */
256 while(Y
->left
!= &SENTINEL
) {
261 /* X is Y's only child */
262 if(Y
->left
!= &SENTINEL
) {
269 /* remove Y from the parent chain */
270 X
->parent
= Y
->parent
;
272 if(Y
== Y
->parent
->left
) {
276 Y
->parent
->right
= X
;
288 if(Z
== Z
->parent
->left
) {
310 void DeleteFixup(RBNODE
*X
) {
312 /*************************************
313 * maintain red-black tree balance *
314 * after deleting node X *
315 *************************************/
317 while (X
!= ROOT
&& X
->color
== BLACK
) {
318 if(X
== X
->parent
->left
) {
319 RBNODE
*W
= X
->parent
->right
;
320 if(W
->color
== RED
) {
322 X
->parent
->color
= RED
;
323 RotateLeft (X
->parent
);
324 W
= X
->parent
->right
;
326 if(W
->left
->color
== BLACK
&& W
->right
->color
== BLACK
) {
331 if(W
->right
->color
== BLACK
) {
332 W
->left
->color
= BLACK
;
335 W
= X
->parent
->right
;
337 W
->color
= X
->parent
->color
;
338 X
->parent
->color
= BLACK
;
339 W
->right
->color
= BLACK
;
340 RotateLeft (X
->parent
);
345 RBNODE
*W
= X
->parent
->left
;
346 if(W
->color
== RED
) {
348 X
->parent
->color
= RED
;
349 RotateRight (X
->parent
);
352 if(W
->right
->color
== BLACK
&& W
->left
->color
== BLACK
) {
357 if(W
->left
->color
== BLACK
) {
358 W
->right
->color
= BLACK
;
363 W
->color
= X
->parent
->color
;
364 X
->parent
->color
= BLACK
;
365 W
->left
->color
= BLACK
;
366 RotateRight (X
->parent
);
375 static RBNODE
*FindClosestNode(unsigned long data
) {
377 RBNODE
*current
= ROOT
;
379 /* Finds the node containing data, or the next higher one. Always
380 check the resulting node. It can be a Sentinel node, or if there
381 is no node higher than or equal to data then the previous node
384 while(current
!= &SENTINEL
) {
386 if(CompEQ(data
, current
->DATA
)) {
390 current
= CompLT(data
, current
->DATA
) ? current
->left
: current
->right
;
397 RBNODE
*FindNode(unsigned long data
) {
398 RBNODE
*current
= ROOT
;
400 /*******************************
401 * find node containing data *
402 *******************************/
404 while(current
!= &SENTINEL
) {
405 if(CompEQ(data
, current
->DATA
)) {
409 current
= CompLT(data
, current
->DATA
) ? current
->left
: current
->right
;
417 RBNODE
*FindNodeFrom(RBNODE
*current
,unsigned long data
) {
419 /*******************************
420 * find node containing data *
421 *******************************/
423 while(current
!= &SENTINEL
) {
424 if(CompEQ(data
, current
->DATA
)) {
428 current
= CompLT(data
, current
->DATA
) ? current
->left
: current
->right
;
438 /* Call with FindAllNodes(ROOT,...); */
440 static void FindAllNodes(RBNODE
*current
,unsigned long data
) {
442 /************************************
443 * find all nodes containing Data *
444 ************************************/
446 if(current
!= &SENTINEL
) {
447 if(CompEQ(data
, current
->DATA
)) {
449 // do something with Current here.
451 FindAllNodes(current
->left
,data
);
452 FindAllNodes(current
->right
,data
);
455 CompLT(data
, current
->DATA
) ? FindAllNodes(current
->left
,data
) : FindAllNodes(current
->right
,data
);
462 void WalkTree(RBNODE
*current
) {
463 if(current
!=&SENTINEL
) {
464 WalkTree(current
->left
);
465 WalkTree(current
->right
);
471 RBNODE
*FirstNode(void) {
474 /* This function returns the first node, or 0 if there are no nodes at all. */
480 while(n
->left
!= &SENTINEL
) {
488 RBNODE
*NextNode(RBNODE
*n
) {
489 // cop(n, "nextnode 1");
491 if(n
->right
!= &SENTINEL
) {
493 while(n
->left
!= &SENTINEL
) {
495 // cop(n, "nextnode 2");
500 while(n
->parent
!=0) {
501 if(n
->parent
->left
== n
) {
506 // cop(n, "nextnode 3");