revert between 56095 -> 55830 in arch
[AROS.git] / rom / filesys / SFS / FS / redblacktree.c
blob5f9271dbd6fb13f1a7e5c36d2610633c87589f8d
2 #include "redblacktree.h"
4 /* The constants below must be defined in the file which includes
5 the redblacktree.c code. */
7 #if 0
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)
18 #endif
21 /* Example RBTreeNode structure:
23 struct RBTreeNode {
24 struct RBTreeNode *left;
25 struct RBTreeNode *right;
26 struct RBTreeNode *parent;
27 UWORD magicvalue;
28 NodeColor color;
29 unsigned long data;
34 /* prototypes */
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);
44 #if 0
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 */
49 #endif
53 void InitRedBlackTree(void) {
54 ROOT=&SENTINEL;
55 SENTINEL.left=&SENTINEL;
56 SENTINEL.right=&SENTINEL;
57 SENTINEL.parent=0;
58 SENTINEL.color=BLACK;
59 // SENTINEL.magicvalue=0x4a4f;
60 SENTINEL.DATA=0;
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 */
73 current = ROOT;
74 parent = 0;
75 while (current != &SENTINEL) {
76 // if(CompEQ(X->DATA, current->DATA)) return (current);
77 parent = current;
78 current = CompLT(X->DATA, current->DATA) ? current->left : current->right;
81 X->parent = parent;
82 X->left = &SENTINEL;
83 X->right = &SENTINEL;
84 X->color = RED;
86 /* insert node in tree */
87 if(parent) {
88 if(CompLT(X->DATA, parent->DATA)) {
89 parent->left = X;
91 else {
92 parent->right = X;
95 else {
96 ROOT = X;
99 InsertFixup(X);
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) {
117 /* uncle is red */
118 X->parent->color = BLACK;
119 Y->color = BLACK;
120 X->parent->parent->color = RED;
121 X = X->parent->parent;
123 else {
124 /* uncle is black */
125 if(X == X->parent->right) {
126 /* make X a left child */
127 X = X->parent;
128 RotateLeft(X);
131 /* recolor and rotate */
132 X->parent->color = BLACK;
133 X->parent->parent->color = RED;
134 RotateRight(X->parent->parent);
137 else {
138 /* mirror image of above code */
139 RBNODE *Y = X->parent->parent->left;
140 if(Y->color == RED) {
142 /* uncle is red */
143 X->parent->color = BLACK;
144 Y->color = BLACK;
145 X->parent->parent->color = RED;
146 X = X->parent->parent;
148 else {
149 /* uncle is black */
150 if(X == X->parent->left) {
151 X = X->parent;
152 RotateRight(X);
154 X->parent->color = BLACK;
155 X->parent->parent->color = RED;
156 RotateLeft(X->parent->parent);
160 ROOT->color = BLACK;
163 void RotateLeft(RBNODE *X) {
165 /**************************
166 * rotate Node X to left *
167 **************************/
169 RBNODE *Y = X->right;
171 /* establish X->right link */
172 X->right = Y->left;
173 if(Y->left != &SENTINEL) {
174 Y->left->parent = X;
177 /* establish Y->parent link */
178 if(Y != &SENTINEL) {
179 Y->parent = X->parent;
181 if(X->parent) {
182 if(X == X->parent->left) {
183 X->parent->left = Y;
185 else {
186 X->parent->right = Y;
189 else {
190 ROOT = Y;
193 /* link X and Y */
194 Y->left = X;
195 if(X != &SENTINEL) {
196 X->parent = Y;
200 void RotateRight(RBNODE *X) {
202 /****************************
203 * rotate Node X to right *
204 ****************************/
206 RBNODE *Y = X->left;
208 /* establish X->left link */
209 X->left = Y->right;
210 if(Y->right != &SENTINEL) {
211 Y->right->parent = X;
214 /* establish Y->parent link */
215 if(Y != &SENTINEL) {
216 Y->parent = X->parent;
218 if(X->parent) {
219 if(X == X->parent->right) {
220 X->parent->right = Y;
222 else {
223 X->parent->left = Y;
226 else {
227 ROOT = Y;
230 /* link X and Y */
231 Y->right = X;
232 if(X != &SENTINEL) {
233 X->parent = Y;
237 static void DeleteNode(RBNODE *Z) {
238 RBNODE *X, *Y;
239 NodeColor c;
241 /*****************************
242 * delete node Z from tree *
243 *****************************/
245 if(!Z || Z == &SENTINEL) {
246 return;
249 if(Z->left == &SENTINEL || Z->right == &SENTINEL) {
250 /* Y has a &SENTINEL node as a child */
251 Y = Z;
253 else {
254 /* find tree successor with a &SENTINEL node as a child */
255 Y = Z->right;
256 while(Y->left != &SENTINEL) {
257 Y = Y->left;
261 /* X is Y's only child */
262 if(Y->left != &SENTINEL) {
263 X = Y->left;
265 else {
266 X = Y->right;
269 /* remove Y from the parent chain */
270 X->parent = Y->parent;
271 if(Y->parent) {
272 if(Y == Y->parent->left) {
273 Y->parent->left = X;
275 else {
276 Y->parent->right = X;
279 else {
280 ROOT = X;
283 c=Y->color;
285 if(Y != Z) {
286 Y->parent=Z->parent;
287 if(Z->parent!=0) {
288 if(Z == Z->parent->left) {
289 Z->parent->left=Y;
291 else {
292 Z->parent->right=Y;
295 else {
296 ROOT=Y;
299 Y->left=Z->left;
300 Y->right=Z->right;
301 Y->left->parent=Y;
302 Y->right->parent=Y;
303 Y->color=Z->color;
305 if(c == BLACK) {
306 DeleteFixup(X);
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) {
321 W->color = BLACK;
322 X->parent->color = RED;
323 RotateLeft (X->parent);
324 W = X->parent->right;
326 if(W->left->color == BLACK && W->right->color == BLACK) {
327 W->color = RED;
328 X = X->parent;
330 else {
331 if(W->right->color == BLACK) {
332 W->left->color = BLACK;
333 W->color = RED;
334 RotateRight (W);
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);
341 X = ROOT;
344 else {
345 RBNODE *W = X->parent->left;
346 if(W->color == RED) {
347 W->color = BLACK;
348 X->parent->color = RED;
349 RotateRight (X->parent);
350 W = X->parent->left;
352 if(W->right->color == BLACK && W->left->color == BLACK) {
353 W->color = RED;
354 X = X->parent;
356 else {
357 if(W->left->color == BLACK) {
358 W->right->color = BLACK;
359 W->color = RED;
360 RotateLeft (W);
361 W = X->parent->left;
363 W->color = X->parent->color;
364 X->parent->color = BLACK;
365 W->left->color = BLACK;
366 RotateRight (X->parent);
367 X = ROOT;
371 X->color = BLACK;
374 #ifdef DEBUGCODE
375 static RBNODE *FindClosestNode(unsigned long data) {
376 RBNODE *closest=0;
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
382 will be returned. */
384 while(current != &SENTINEL) {
385 closest=current;
386 if(CompEQ(data, current->DATA)) {
387 return (current);
389 else {
390 current = CompLT(data, current->DATA) ? current->left : current->right;
393 return(closest);
395 #endif
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)) {
406 return (current);
408 else {
409 current = CompLT(data, current->DATA) ? current->left : current->right;
412 return(0);
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)) {
425 return (current);
427 else {
428 current = CompLT(data, current->DATA) ? current->left : current->right;
431 return(0);
437 #ifdef DEBUGCODE
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);
454 else {
455 CompLT(data, current->DATA) ? FindAllNodes(current->left,data) : FindAllNodes(current->right,data);
459 #endif
462 void WalkTree(RBNODE *current) {
463 if(current!=&SENTINEL) {
464 WalkTree(current->left);
465 WalkTree(current->right);
471 RBNODE *FirstNode(void) {
472 RBNODE *n=ROOT;
474 /* This function returns the first node, or 0 if there are no nodes at all. */
476 if(n==&SENTINEL) {
477 return(0);
480 while(n->left != &SENTINEL) {
481 n=n->left;
484 return(n);
488 RBNODE *NextNode(RBNODE *n) {
489 // cop(n, "nextnode 1");
491 if(n->right != &SENTINEL) {
492 n=n->right;
493 while(n->left != &SENTINEL) {
494 n=n->left;
495 // cop(n, "nextnode 2");
497 return(n);
500 while(n->parent!=0) {
501 if(n->parent->left == n) {
502 break;
505 n=n->parent;
506 // cop(n, "nextnode 3");
509 return(n->parent);