Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
red_black_tree.c
Go to the documentation of this file.
1/**********************************************************
2* See the LICENSE file for copyright information. *
3**********************************************************/
4
5#include "config.h"
6
7#include <assert.h>
9#include <stdio.h>
10#include <stdlib.h>
11
12/***********************************************************************/
13/* FUNCTION: RBTreeCreate */
14
15/* INPUTS: All the inputs are names of functions. CompFunc takes to */
16/* void pointers to keys and returns 1 if the first argument is */
17/* "greater than" the second. DestFunc takes a pointer to a key and */
18/* destroys it in the appropriate manner when the node containing that */
19/* key is deleted. */
20
21/* OUTPUT: This function returns a pointer to the newly created */
22/* red-black tree. */
23
24/* Modifies Input: none */
25/***********************************************************************/
26
27rb_red_blk_tree* RBTreeCreate( int (*CompFunc) (const void*,const void*),
28 void (*DestFunc)(void *)) {
29 rb_red_blk_tree* newTree = NULL;
30 rb_red_blk_node* temp;
31
32 newTree= malloc(sizeof(rb_red_blk_tree));
33 if (newTree == NULL) {
34 return NULL;
35 }
36 newTree->nil = newTree->root = NULL;
37 newTree->Compare= CompFunc;
38 newTree->DestroyKey= DestFunc;
39
40 /* see the comment in the rb_red_blk_tree structure in red_black_tree.h */
41 /* for information on nil and root */
42 temp=newTree->nil= malloc(sizeof(rb_red_blk_node));
43 if (temp == NULL) {
44 free(newTree);
45 return NULL;
46 }
47 temp->parent=temp->left=temp->right=temp;
48 temp->red=0;
49 temp->key=0;
50 temp=newTree->root= malloc(sizeof(rb_red_blk_node));
51 if (temp == NULL) {
52 free(newTree->nil);
53 free(newTree);
54 return NULL;
55 }
56 temp->parent=temp->left=temp->right=newTree->nil;
57 temp->key=0;
58 temp->red=0;
59 return newTree;
60}
61
62/***********************************************************************/
63/* FUNCTION: LeftRotate */
64
65/* INPUTS: This takes a tree so that it can access the appropriate */
66/* root and nil pointers, and the node to rotate on. */
67
68/* OUTPUT: None */
69
70/* Modifies Input: tree, x */
71
72/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
73/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
74/* makes the parent of x be to the left of x, x the parent of */
75/* its parent before the rotation and fixes other pointers */
76/* accordingly. */
77/***********************************************************************/
78
81 rb_red_blk_node* nil=tree->nil;
82
83 /* I originally wrote this function to use the sentinel for */
84 /* nil to avoid checking for nil. However this introduces a */
85 /* very subtle bug because sometimes this function modifies */
86 /* the parent pointer of nil. This can be a problem if a */
87 /* function which calls LeftRotate also uses the nil sentinel */
88 /* and expects the nil sentinel's parent pointer to be unchanged */
89 /* after calling this function. For example, when RBDeleteFixUP */
90 /* calls LeftRotate it expects the parent pointer of nil to be */
91 /* unchanged. */
92
93 y=x->right;
94 x->right=y->left;
95
96 if (y->left != nil) y->left->parent=x; /* used to use sentinel here */
97 /* and do an unconditional assignment instead of testing for nil */
98
99 y->parent=x->parent;
100
101 /* instead of checking if x->parent is the root as in the book, we */
102 /* count on the root sentinel to implicitly take care of this case */
103 if( x == x->parent->left) {
104 x->parent->left=y;
105 } else {
106 x->parent->right=y;
107 }
108 y->left=x;
109 x->parent=y;
110
111 assert(!tree->nil->red && "nil not red in LeftRotate");
112}
113
114
115/***********************************************************************/
116/* FUNCTION: RighttRotate */
117
118/* INPUTS: This takes a tree so that it can access the appropriate */
119/* root and nil pointers, and the node to rotate on. */
120
121/* OUTPUT: None */
122
123/* Modifies Input?: tree, y */
124
125/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
126/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
127/* makes the parent of x be to the left of x, x the parent of */
128/* its parent before the rotation and fixes other pointers */
129/* accordingly. */
130/***********************************************************************/
131
134 rb_red_blk_node* nil=tree->nil;
135
136 /* I originally wrote this function to use the sentinel for */
137 /* nil to avoid checking for nil. However this introduces a */
138 /* very subtle bug because sometimes this function modifies */
139 /* the parent pointer of nil. This can be a problem if a */
140 /* function which calls LeftRotate also uses the nil sentinel */
141 /* and expects the nil sentinel's parent pointer to be unchanged */
142 /* after calling this function. For example, when RBDeleteFixUP */
143 /* calls LeftRotate it expects the parent pointer of nil to be */
144 /* unchanged. */
145
146 x=y->left;
147 y->left=x->right;
148
149 if (nil != x->right) x->right->parent=y; /*used to use sentinel here */
150 /* and do an unconditional assignment instead of testing for nil */
151
152 /* instead of checking if x->parent is the root as in the book, we */
153 /* count on the root sentinel to implicitly take care of this case */
154 x->parent=y->parent;
155 if( y == y->parent->left) {
156 y->parent->left=x;
157 } else {
158 y->parent->right=x;
159 }
160 x->right=y;
161 y->parent=x;
162
163 assert(!tree->nil->red && "nil not red in RightRotate");
164}
165
166/***********************************************************************/
167/* FUNCTION: TreeInsertHelp */
168
169/* INPUTS: tree is the tree to insert into and z is the node to insert */
170
171/* OUTPUT: none */
172
173/* Modifies Input: tree, z */
174
175/* EFFECTS: Inserts z into the tree as if it were a regular binary tree */
176/* using the algorithm described in _Introduction_To_Algorithms_ */
177/* by Cormen et al. This function is only intended to be called */
178/* by the RBTreeInsert function and not by the user */
179/***********************************************************************/
180
182 /* This function should only be called by InsertRBTree (see above) */
185 rb_red_blk_node* nil=tree->nil;
186
187 z->left=z->right=nil;
188 y=tree->root;
189 x=tree->root->left;
190 while( x != nil) {
191 y=x;
192 if (1 == tree->Compare(x->key,z->key)) { /* x.key > z.key */
193 x=x->left;
194 } else { /* x,key <= z.key */
195 x=x->right;
196 }
197 }
198 z->parent=y;
199 if ( (y == tree->root) ||
200 (1 == tree->Compare(y->key,z->key))) { /* y.key > z.key */
201 y->left=z;
202 } else {
203 y->right=z;
204 }
205
206 assert(!tree->nil->red && "nil not red in TreeInsertHelp");
207}
208
209/* Before calling Insert RBTree the node x should have its key set */
210
211/***********************************************************************/
212/* FUNCTION: RBTreeInsert */
213
214/* INPUTS: tree is the red-black tree to insert a node which has a key */
215/* pointed to by key. */
216
217/* OUTPUT: This function returns a pointer to the newly inserted node */
218/* which is guarunteed to be valid until this node is deleted. */
219/* What this means is if another data structure stores this */
220/* pointer then the tree does not need to be searched when this */
221/* is to be deleted. */
222
223/* Modifies Input: tree */
224
225/* EFFECTS: Creates a node node which contains the appropriate key */
226/* pointer and inserts it into the tree. */
227/***********************************************************************/
228
230 rb_red_blk_node * y;
231 rb_red_blk_node * x;
233
234 x= malloc(sizeof(rb_red_blk_node));
235 if (x == NULL) {
236 return NULL;
237 }
238 x->key=key;
239
241 newNode=x;
242 x->red=1;
243 while(x->parent->red) { /* use sentinel instead of checking for root */
244 if (x->parent == x->parent->parent->left) {
245 y=x->parent->parent->right;
246 if (y->red) {
247 x->parent->red=0;
248 y->red=0;
249 x->parent->parent->red=1;
250 x=x->parent->parent;
251 } else {
252 if (x == x->parent->right) {
253 x=x->parent;
254 LeftRotate(tree,x);
255 }
256 x->parent->red=0;
257 x->parent->parent->red=1;
259 }
260 } else { /* case for x->parent == x->parent->parent->right */
261 y=x->parent->parent->left;
262 if (y->red) {
263 x->parent->red=0;
264 y->red=0;
265 x->parent->parent->red=1;
266 x=x->parent->parent;
267 } else {
268 if (x == x->parent->left) {
269 x=x->parent;
270 RightRotate(tree,x);
271 }
272 x->parent->red=0;
273 x->parent->parent->red=1;
275 }
276 }
277 }
278 tree->root->left->red=0;
279 return newNode;
280}
281
282/***********************************************************************/
283/* FUNCTION: TreeSuccessor */
284
285/* INPUTS: tree is the tree in question, and x is the node we want the */
286/* the successor of. */
287
288/* OUTPUT: This function returns the successor of x or NULL if no */
289/* successor exists. */
290
291/* Modifies Input: none */
292
293/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
294/***********************************************************************/
295
298 rb_red_blk_node* nil=tree->nil;
299 rb_red_blk_node* root=tree->root;
300
301 if (nil != (y = x->right)) { /* assignment to y is intentional */
302 while(y->left != nil) { /* returns the minium of the right subtree of x */
303 y=y->left;
304 }
305 return y;
306 } else {
307 y=x->parent;
308 while(x == y->right) { /* sentinel used instead of checking for nil */
309 x=y;
310 y=y->parent;
311 }
312 if (y == root) return nil;
313 return y;
314 }
315}
316
317/***********************************************************************/
318/* FUNCTION: Treepredecessor */
319
320/* INPUTS: tree is the tree in question, and x is the node we want the */
321/* the predecessor of. */
322
323/* OUTPUT: This function returns the predecessor of x or NULL if no */
324/* predecessor exists. */
325
326/* Modifies Input: none */
327
328/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
329/***********************************************************************/
330
333 rb_red_blk_node* nil=tree->nil;
334 rb_red_blk_node* root=tree->root;
335
336 if (nil != (y = x->left)) { /* assignment to y is intentional */
337 while(y->right != nil) { /* returns the maximum of the left subtree of x */
338 y=y->right;
339 }
340 return y;
341 } else {
342 y=x->parent;
343 while(x == y->left) {
344 if (y == root) return nil;
345 x=y;
346 y=y->parent;
347 }
348 return y;
349 }
350}
351
352/***********************************************************************/
353/* FUNCTION: TreeDestHelper */
354
355/* INPUTS: tree is the tree to destroy and x is the current node */
356
357/* OUTPUT: none */
358
359/* EFFECTS: This function recursively destroys the nodes of the tree */
360/* postorder using the DestroyKey and DestroyInfo functions. */
361
362/* Modifies Input: tree, x */
363
364/* Note: This function should only be called by RBTreeDestroy */
365/***********************************************************************/
366
368 rb_red_blk_node* nil=tree->nil;
369 if (x != nil) {
372 tree->DestroyKey(x->key);
373 free(x);
374 }
375}
376
377
378/***********************************************************************/
379/* FUNCTION: RBTreeDestroy */
380
381/* INPUTS: tree is the tree to destroy */
382
383/* OUTPUT: none */
384
385/* EFFECT: Destroys the key and frees memory */
386
387/* Modifies Input: tree */
388
389/***********************************************************************/
390
392 TreeDestHelper(tree,tree->root->left);
393 free(tree->root);
394 free(tree->nil);
395 free(tree);
396}
397
398/***********************************************************************/
399/* FUNCTION: RBExactQuery */
400
401/* INPUTS: tree is the tree to print and q is a pointer to the key */
402/* we are searching for */
403
404/* OUTPUT: returns the a node with key equal to q. If there are */
405/* multiple nodes with key equal to q this function returns */
406/* the one highest in the tree */
407
408/* Modifies Input: none */
409
410/***********************************************************************/
411
413 rb_red_blk_node* x=tree->root->left;
414 rb_red_blk_node* nil=tree->nil;
415 int compVal;
416 if (x == nil) return 0;
417 compVal = tree->Compare(x->key, q);
418 while(0 != compVal) {/*assignemnt*/
419 if (1 == compVal) { /* x->key > q */
420 x=x->left;
421 } else {
422 x=x->right;
423 }
424 if ( x == nil) return 0;
425 compVal = tree->Compare(x->key, q);
426 }
427 return x;
428}
429
430
431/***********************************************************************/
432/* FUNCTION: RBDeleteFixUp */
433
434/* INPUTS: tree is the tree to fix and x is the child of the spliced */
435/* out node in RBTreeDelete. */
436
437/* OUTPUT: none */
438
439/* EFFECT: Performs rotations and changes colors to restore red-black */
440/* properties after a node is deleted */
441
442/* Modifies Input: tree, x */
443
444/* The algorithm from this function is from _Introduction_To_Algorithms_ */
445/***********************************************************************/
446
448 rb_red_blk_node* root=tree->root->left;
450
451 while( (!x->red) && (root != x)) {
452 if (x == x->parent->left) {
453 w=x->parent->right;
454 if (w->red) {
455 w->red=0;
456 x->parent->red=1;
458 w=x->parent->right;
459 }
460 if ( (!w->right->red) && (!w->left->red) ) {
461 w->red=1;
462 x=x->parent;
463 } else {
464 if (!w->right->red) {
465 w->left->red=0;
466 w->red=1;
467 RightRotate(tree,w);
468 w=x->parent->right;
469 }
470 w->red=x->parent->red;
471 x->parent->red=0;
472 w->right->red=0;
474 x=root; /* this is to exit while loop */
475 }
476 } else { // the code below has left and right switched from above
477 w=x->parent->left;
478 if (w->red) {
479 w->red=0;
480 x->parent->red=1;
482 w=x->parent->left;
483 }
484 if ( (!w->right->red) && (!w->left->red) ) {
485 w->red=1;
486 x=x->parent;
487 } else {
488 if (!w->left->red) {
489 w->right->red=0;
490 w->red=1;
491 LeftRotate(tree,w);
492 w=x->parent->left;
493 }
494 w->red=x->parent->red;
495 x->parent->red=0;
496 w->left->red=0;
498 x=root; /* this is to exit while loop */
499 }
500 }
501 }
502 x->red=0;
503
504 assert(!tree->nil->red && "nil not black in RBDeleteFixUp");
505}
506
507
508/***********************************************************************/
509/* FUNCTION: RBDelete */
510
511/* INPUTS: tree is the tree to delete node z from */
512
513/* OUTPUT: none */
514
515/* EFFECT: Deletes z from tree and frees the key of z */
516/* using DestroyKey. Then calls */
517/* RBDeleteFixUp to restore red-black properties */
518
519/* Modifies Input: tree, z */
520
521/* The algorithm from this function is from _Introduction_To_Algorithms_ */
522/***********************************************************************/
523
527 rb_red_blk_node* nil=tree->nil;
528 rb_red_blk_node* root=tree->root;
529
530 y= ((z->left == nil) || (z->right == nil)) ? z : TreeSuccessor(tree,z);
531 x= (y->left == nil) ? y->right : y->left;
532 if (root == (x->parent = y->parent)) { /* assignment of y->p to x->p is intentional */
533 root->left=x;
534 } else {
535 if (y == y->parent->left) {
536 y->parent->left=x;
537 } else {
538 y->parent->right=x;
539 }
540 }
541 if (y != z) { /* y should not be nil in this case */
542
543 assert(y!=tree->nil && "y is nil in RBDelete");
544 /* y is the node to splice out and x is its child */
545
546 if (!(y->red)) RBDeleteFixUp(tree,x);
547
548 tree->DestroyKey(z->key);
549 y->left=z->left;
550 y->right=z->right;
551 y->parent=z->parent;
552 y->red=z->red;
553 z->left->parent=z->right->parent=y;
554 if (z == z->parent->left) {
555 z->parent->left=y;
556 } else {
557 z->parent->right=y;
558 }
559 free(z);
560 } else {
561 tree->DestroyKey(y->key);
562 if (!(y->red)) RBDeleteFixUp(tree,x);
563 free(y);
564 }
565
566 assert(!tree->nil->red && "nil not black in RBDelete");
567}
disc key
Definition exparse.y:214
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:149
static node_list * newNode(Grid *g, Agnode_t *n, node_list *nxt)
Definition grid.c:138
@ tree
Definition gvgen.c:33
static int z
void RBDelete(rb_red_blk_tree *tree, rb_red_blk_node *z)
rb_red_blk_node * TreePredecessor(rb_red_blk_tree *tree, rb_red_blk_node *x)
void RBTreeDestroy(rb_red_blk_tree *tree)
static void RightRotate(rb_red_blk_tree *tree, rb_red_blk_node *y)
rb_red_blk_node * RBExactQuery(rb_red_blk_tree *tree, void *q)
static void LeftRotate(rb_red_blk_tree *tree, rb_red_blk_node *x)
static void TreeDestHelper(rb_red_blk_tree *tree, rb_red_blk_node *x)
rb_red_blk_node * RBTreeInsert(rb_red_blk_tree *tree, void *key)
static void RBDeleteFixUp(rb_red_blk_tree *tree, rb_red_blk_node *x)
rb_red_blk_node * TreeSuccessor(rb_red_blk_tree *tree, rb_red_blk_node *x)
static void TreeInsertHelp(rb_red_blk_tree *tree, rb_red_blk_node *z)
rb_red_blk_tree * RBTreeCreate(int(*CompFunc)(const void *, const void *), void(*DestFunc)(void *))
struct rb_red_blk_node * right
struct rb_red_blk_node * parent
struct rb_red_blk_node * left
rb_red_blk_node * nil
int(* Compare)(const void *a, const void *b)
rb_red_blk_node * root
void(* DestroyKey)(void *a)