/src/postgres/src/backend/lib/rbtree.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * rbtree.c |
4 | | * implementation for PostgreSQL generic Red-Black binary tree package |
5 | | * Adopted from http://algolist.manual.ru/ds/rbtree.php |
6 | | * |
7 | | * This code comes from Thomas Niemann's "Sorting and Searching Algorithms: |
8 | | * a Cookbook". |
9 | | * |
10 | | * See http://www.cs.auckland.ac.nz/software/AlgAnim/niemann/s_man.htm for |
11 | | * license terms: "Source code, when part of a software project, may be used |
12 | | * freely without reference to the author." |
13 | | * |
14 | | * Red-black trees are a type of balanced binary tree wherein (1) any child of |
15 | | * a red node is always black, and (2) every path from root to leaf traverses |
16 | | * an equal number of black nodes. From these properties, it follows that the |
17 | | * longest path from root to leaf is only about twice as long as the shortest, |
18 | | * so lookups are guaranteed to run in O(lg n) time. |
19 | | * |
20 | | * Copyright (c) 2009-2025, PostgreSQL Global Development Group |
21 | | * |
22 | | * IDENTIFICATION |
23 | | * src/backend/lib/rbtree.c |
24 | | * |
25 | | *------------------------------------------------------------------------- |
26 | | */ |
27 | | #include "postgres.h" |
28 | | |
29 | | #include "lib/rbtree.h" |
30 | | |
31 | | |
32 | | /* |
33 | | * Colors of nodes (values of RBTNode.color) |
34 | | */ |
35 | 0 | #define RBTBLACK (0) |
36 | 0 | #define RBTRED (1) |
37 | | |
38 | | /* |
39 | | * RBTree control structure |
40 | | */ |
41 | | struct RBTree |
42 | | { |
43 | | RBTNode *root; /* root node, or RBTNIL if tree is empty */ |
44 | | |
45 | | /* Remaining fields are constant after rbt_create */ |
46 | | |
47 | | Size node_size; /* actual size of tree nodes */ |
48 | | /* The caller-supplied manipulation functions */ |
49 | | rbt_comparator comparator; |
50 | | rbt_combiner combiner; |
51 | | rbt_allocfunc allocfunc; |
52 | | rbt_freefunc freefunc; |
53 | | /* Passthrough arg passed to all manipulation functions */ |
54 | | void *arg; |
55 | | }; |
56 | | |
57 | | /* |
58 | | * all leafs are sentinels, use customized NIL name to prevent |
59 | | * collision with system-wide constant NIL which is actually NULL |
60 | | */ |
61 | 0 | #define RBTNIL (&sentinel) |
62 | | |
63 | | static RBTNode sentinel = |
64 | | { |
65 | | .color = RBTBLACK,.left = RBTNIL,.right = RBTNIL,.parent = NULL |
66 | | }; |
67 | | |
68 | | |
69 | | /* |
70 | | * rbt_create: create an empty RBTree |
71 | | * |
72 | | * Arguments are: |
73 | | * node_size: actual size of tree nodes (> sizeof(RBTNode)) |
74 | | * The manipulation functions: |
75 | | * comparator: compare two RBTNodes for less/equal/greater |
76 | | * combiner: merge an existing tree entry with a new one |
77 | | * allocfunc: allocate a new RBTNode |
78 | | * freefunc: free an old RBTNode |
79 | | * arg: passthrough pointer that will be passed to the manipulation functions |
80 | | * |
81 | | * Note that the combiner's righthand argument will be a "proposed" tree node, |
82 | | * ie the input to rbt_insert, in which the RBTNode fields themselves aren't |
83 | | * valid. Similarly, either input to the comparator may be a "proposed" node. |
84 | | * This shouldn't matter since the functions aren't supposed to look at the |
85 | | * RBTNode fields, only the extra fields of the struct the RBTNode is embedded |
86 | | * in. |
87 | | * |
88 | | * The freefunc should just be pfree or equivalent; it should NOT attempt |
89 | | * to free any subsidiary data, because the node passed to it may not contain |
90 | | * valid data! freefunc can be NULL if caller doesn't require retail |
91 | | * space reclamation. |
92 | | * |
93 | | * The RBTree node is palloc'd in the caller's memory context. Note that |
94 | | * all contents of the tree are actually allocated by the caller, not here. |
95 | | * |
96 | | * Since tree contents are managed by the caller, there is currently not |
97 | | * an explicit "destroy" operation; typically a tree would be freed by |
98 | | * resetting or deleting the memory context it's stored in. You can pfree |
99 | | * the RBTree node if you feel the urge. |
100 | | */ |
101 | | RBTree * |
102 | | rbt_create(Size node_size, |
103 | | rbt_comparator comparator, |
104 | | rbt_combiner combiner, |
105 | | rbt_allocfunc allocfunc, |
106 | | rbt_freefunc freefunc, |
107 | | void *arg) |
108 | 0 | { |
109 | 0 | RBTree *tree = (RBTree *) palloc(sizeof(RBTree)); |
110 | |
|
111 | 0 | Assert(node_size > sizeof(RBTNode)); |
112 | |
|
113 | 0 | tree->root = RBTNIL; |
114 | 0 | tree->node_size = node_size; |
115 | 0 | tree->comparator = comparator; |
116 | 0 | tree->combiner = combiner; |
117 | 0 | tree->allocfunc = allocfunc; |
118 | 0 | tree->freefunc = freefunc; |
119 | |
|
120 | 0 | tree->arg = arg; |
121 | |
|
122 | 0 | return tree; |
123 | 0 | } |
124 | | |
125 | | /* Copy the additional data fields from one RBTNode to another */ |
126 | | static inline void |
127 | | rbt_copy_data(RBTree *rbt, RBTNode *dest, const RBTNode *src) |
128 | 0 | { |
129 | 0 | memcpy(dest + 1, src + 1, rbt->node_size - sizeof(RBTNode)); |
130 | 0 | } |
131 | | |
132 | | /********************************************************************** |
133 | | * Search * |
134 | | **********************************************************************/ |
135 | | |
136 | | /* |
137 | | * rbt_find: search for a value in an RBTree |
138 | | * |
139 | | * data represents the value to try to find. Its RBTNode fields need not |
140 | | * be valid, it's the extra data in the larger struct that is of interest. |
141 | | * |
142 | | * Returns the matching tree entry, or NULL if no match is found. |
143 | | */ |
144 | | RBTNode * |
145 | | rbt_find(RBTree *rbt, const RBTNode *data) |
146 | 0 | { |
147 | 0 | RBTNode *node = rbt->root; |
148 | |
|
149 | 0 | while (node != RBTNIL) |
150 | 0 | { |
151 | 0 | int cmp = rbt->comparator(data, node, rbt->arg); |
152 | |
|
153 | 0 | if (cmp == 0) |
154 | 0 | return node; |
155 | 0 | else if (cmp < 0) |
156 | 0 | node = node->left; |
157 | 0 | else |
158 | 0 | node = node->right; |
159 | 0 | } |
160 | | |
161 | 0 | return NULL; |
162 | 0 | } |
163 | | |
164 | | /* |
165 | | * rbt_find_great: search for a greater value in an RBTree |
166 | | * |
167 | | * If equal_match is true, this will be a great or equal search. |
168 | | * |
169 | | * Returns the matching tree entry, or NULL if no match is found. |
170 | | */ |
171 | | RBTNode * |
172 | | rbt_find_great(RBTree *rbt, const RBTNode *data, bool equal_match) |
173 | 0 | { |
174 | 0 | RBTNode *node = rbt->root; |
175 | 0 | RBTNode *greater = NULL; |
176 | |
|
177 | 0 | while (node != RBTNIL) |
178 | 0 | { |
179 | 0 | int cmp = rbt->comparator(data, node, rbt->arg); |
180 | |
|
181 | 0 | if (equal_match && cmp == 0) |
182 | 0 | return node; |
183 | 0 | else if (cmp < 0) |
184 | 0 | { |
185 | 0 | greater = node; |
186 | 0 | node = node->left; |
187 | 0 | } |
188 | 0 | else |
189 | 0 | node = node->right; |
190 | 0 | } |
191 | | |
192 | 0 | return greater; |
193 | 0 | } |
194 | | |
195 | | /* |
196 | | * rbt_find_less: search for a lesser value in an RBTree |
197 | | * |
198 | | * If equal_match is true, this will be a less or equal search. |
199 | | * |
200 | | * Returns the matching tree entry, or NULL if no match is found. |
201 | | */ |
202 | | RBTNode * |
203 | | rbt_find_less(RBTree *rbt, const RBTNode *data, bool equal_match) |
204 | 0 | { |
205 | 0 | RBTNode *node = rbt->root; |
206 | 0 | RBTNode *lesser = NULL; |
207 | |
|
208 | 0 | while (node != RBTNIL) |
209 | 0 | { |
210 | 0 | int cmp = rbt->comparator(data, node, rbt->arg); |
211 | |
|
212 | 0 | if (equal_match && cmp == 0) |
213 | 0 | return node; |
214 | 0 | else if (cmp > 0) |
215 | 0 | { |
216 | 0 | lesser = node; |
217 | 0 | node = node->right; |
218 | 0 | } |
219 | 0 | else |
220 | 0 | node = node->left; |
221 | 0 | } |
222 | | |
223 | 0 | return lesser; |
224 | 0 | } |
225 | | |
226 | | /* |
227 | | * rbt_leftmost: fetch the leftmost (smallest-valued) tree node. |
228 | | * Returns NULL if tree is empty. |
229 | | * |
230 | | * Note: in the original implementation this included an unlink step, but |
231 | | * that's a bit awkward. Just call rbt_delete on the result if that's what |
232 | | * you want. |
233 | | */ |
234 | | RBTNode * |
235 | | rbt_leftmost(RBTree *rbt) |
236 | 0 | { |
237 | 0 | RBTNode *node = rbt->root; |
238 | 0 | RBTNode *leftmost = rbt->root; |
239 | |
|
240 | 0 | while (node != RBTNIL) |
241 | 0 | { |
242 | 0 | leftmost = node; |
243 | 0 | node = node->left; |
244 | 0 | } |
245 | |
|
246 | 0 | if (leftmost != RBTNIL) |
247 | 0 | return leftmost; |
248 | | |
249 | 0 | return NULL; |
250 | 0 | } |
251 | | |
252 | | /********************************************************************** |
253 | | * Insertion * |
254 | | **********************************************************************/ |
255 | | |
256 | | /* |
257 | | * Rotate node x to left. |
258 | | * |
259 | | * x's right child takes its place in the tree, and x becomes the left |
260 | | * child of that node. |
261 | | */ |
262 | | static void |
263 | | rbt_rotate_left(RBTree *rbt, RBTNode *x) |
264 | 0 | { |
265 | 0 | RBTNode *y = x->right; |
266 | | |
267 | | /* establish x->right link */ |
268 | 0 | x->right = y->left; |
269 | 0 | if (y->left != RBTNIL) |
270 | 0 | y->left->parent = x; |
271 | | |
272 | | /* establish y->parent link */ |
273 | 0 | if (y != RBTNIL) |
274 | 0 | y->parent = x->parent; |
275 | 0 | if (x->parent) |
276 | 0 | { |
277 | 0 | if (x == x->parent->left) |
278 | 0 | x->parent->left = y; |
279 | 0 | else |
280 | 0 | x->parent->right = y; |
281 | 0 | } |
282 | 0 | else |
283 | 0 | { |
284 | 0 | rbt->root = y; |
285 | 0 | } |
286 | | |
287 | | /* link x and y */ |
288 | 0 | y->left = x; |
289 | 0 | if (x != RBTNIL) |
290 | 0 | x->parent = y; |
291 | 0 | } |
292 | | |
293 | | /* |
294 | | * Rotate node x to right. |
295 | | * |
296 | | * x's left right child takes its place in the tree, and x becomes the right |
297 | | * child of that node. |
298 | | */ |
299 | | static void |
300 | | rbt_rotate_right(RBTree *rbt, RBTNode *x) |
301 | 0 | { |
302 | 0 | RBTNode *y = x->left; |
303 | | |
304 | | /* establish x->left link */ |
305 | 0 | x->left = y->right; |
306 | 0 | if (y->right != RBTNIL) |
307 | 0 | y->right->parent = x; |
308 | | |
309 | | /* establish y->parent link */ |
310 | 0 | if (y != RBTNIL) |
311 | 0 | y->parent = x->parent; |
312 | 0 | if (x->parent) |
313 | 0 | { |
314 | 0 | if (x == x->parent->right) |
315 | 0 | x->parent->right = y; |
316 | 0 | else |
317 | 0 | x->parent->left = y; |
318 | 0 | } |
319 | 0 | else |
320 | 0 | { |
321 | 0 | rbt->root = y; |
322 | 0 | } |
323 | | |
324 | | /* link x and y */ |
325 | 0 | y->right = x; |
326 | 0 | if (x != RBTNIL) |
327 | 0 | x->parent = y; |
328 | 0 | } |
329 | | |
330 | | /* |
331 | | * Maintain Red-Black tree balance after inserting node x. |
332 | | * |
333 | | * The newly inserted node is always initially marked red. That may lead to |
334 | | * a situation where a red node has a red child, which is prohibited. We can |
335 | | * always fix the problem by a series of color changes and/or "rotations", |
336 | | * which move the problem progressively higher up in the tree. If one of the |
337 | | * two red nodes is the root, we can always fix the problem by changing the |
338 | | * root from red to black. |
339 | | * |
340 | | * (This does not work lower down in the tree because we must also maintain |
341 | | * the invariant that every leaf has equal black-height.) |
342 | | */ |
343 | | static void |
344 | | rbt_insert_fixup(RBTree *rbt, RBTNode *x) |
345 | 0 | { |
346 | | /* |
347 | | * x is always a red node. Initially, it is the newly inserted node. Each |
348 | | * iteration of this loop moves it higher up in the tree. |
349 | | */ |
350 | 0 | while (x != rbt->root && x->parent->color == RBTRED) |
351 | 0 | { |
352 | | /* |
353 | | * x and x->parent are both red. Fix depends on whether x->parent is |
354 | | * a left or right child. In either case, we define y to be the |
355 | | * "uncle" of x, that is, the other child of x's grandparent. |
356 | | * |
357 | | * If the uncle is red, we flip the grandparent to red and its two |
358 | | * children to black. Then we loop around again to check whether the |
359 | | * grandparent still has a problem. |
360 | | * |
361 | | * If the uncle is black, we will perform one or two "rotations" to |
362 | | * balance the tree. Either x or x->parent will take the |
363 | | * grandparent's position in the tree and recolored black, and the |
364 | | * original grandparent will be recolored red and become a child of |
365 | | * that node. This always leaves us with a valid red-black tree, so |
366 | | * the loop will terminate. |
367 | | */ |
368 | 0 | if (x->parent == x->parent->parent->left) |
369 | 0 | { |
370 | 0 | RBTNode *y = x->parent->parent->right; |
371 | |
|
372 | 0 | if (y->color == RBTRED) |
373 | 0 | { |
374 | | /* uncle is RBTRED */ |
375 | 0 | x->parent->color = RBTBLACK; |
376 | 0 | y->color = RBTBLACK; |
377 | 0 | x->parent->parent->color = RBTRED; |
378 | |
|
379 | 0 | x = x->parent->parent; |
380 | 0 | } |
381 | 0 | else |
382 | 0 | { |
383 | | /* uncle is RBTBLACK */ |
384 | 0 | if (x == x->parent->right) |
385 | 0 | { |
386 | | /* make x a left child */ |
387 | 0 | x = x->parent; |
388 | 0 | rbt_rotate_left(rbt, x); |
389 | 0 | } |
390 | | |
391 | | /* recolor and rotate */ |
392 | 0 | x->parent->color = RBTBLACK; |
393 | 0 | x->parent->parent->color = RBTRED; |
394 | |
|
395 | 0 | rbt_rotate_right(rbt, x->parent->parent); |
396 | 0 | } |
397 | 0 | } |
398 | 0 | else |
399 | 0 | { |
400 | | /* mirror image of above code */ |
401 | 0 | RBTNode *y = x->parent->parent->left; |
402 | |
|
403 | 0 | if (y->color == RBTRED) |
404 | 0 | { |
405 | | /* uncle is RBTRED */ |
406 | 0 | x->parent->color = RBTBLACK; |
407 | 0 | y->color = RBTBLACK; |
408 | 0 | x->parent->parent->color = RBTRED; |
409 | |
|
410 | 0 | x = x->parent->parent; |
411 | 0 | } |
412 | 0 | else |
413 | 0 | { |
414 | | /* uncle is RBTBLACK */ |
415 | 0 | if (x == x->parent->left) |
416 | 0 | { |
417 | 0 | x = x->parent; |
418 | 0 | rbt_rotate_right(rbt, x); |
419 | 0 | } |
420 | 0 | x->parent->color = RBTBLACK; |
421 | 0 | x->parent->parent->color = RBTRED; |
422 | |
|
423 | 0 | rbt_rotate_left(rbt, x->parent->parent); |
424 | 0 | } |
425 | 0 | } |
426 | 0 | } |
427 | | |
428 | | /* |
429 | | * The root may already have been black; if not, the black-height of every |
430 | | * node in the tree increases by one. |
431 | | */ |
432 | 0 | rbt->root->color = RBTBLACK; |
433 | 0 | } |
434 | | |
435 | | /* |
436 | | * rbt_insert: insert a new value into the tree. |
437 | | * |
438 | | * data represents the value to insert. Its RBTNode fields need not |
439 | | * be valid, it's the extra data in the larger struct that is of interest. |
440 | | * |
441 | | * If the value represented by "data" is not present in the tree, then |
442 | | * we copy "data" into a new tree entry and return that node, setting *isNew |
443 | | * to true. |
444 | | * |
445 | | * If the value represented by "data" is already present, then we call the |
446 | | * combiner function to merge data into the existing node, and return the |
447 | | * existing node, setting *isNew to false. |
448 | | * |
449 | | * "data" is unmodified in either case; it's typically just a local |
450 | | * variable in the caller. |
451 | | */ |
452 | | RBTNode * |
453 | | rbt_insert(RBTree *rbt, const RBTNode *data, bool *isNew) |
454 | 0 | { |
455 | 0 | RBTNode *current, |
456 | 0 | *parent, |
457 | 0 | *x; |
458 | 0 | int cmp; |
459 | | |
460 | | /* find where node belongs */ |
461 | 0 | current = rbt->root; |
462 | 0 | parent = NULL; |
463 | 0 | cmp = 0; /* just to prevent compiler warning */ |
464 | |
|
465 | 0 | while (current != RBTNIL) |
466 | 0 | { |
467 | 0 | cmp = rbt->comparator(data, current, rbt->arg); |
468 | 0 | if (cmp == 0) |
469 | 0 | { |
470 | | /* |
471 | | * Found node with given key. Apply combiner. |
472 | | */ |
473 | 0 | rbt->combiner(current, data, rbt->arg); |
474 | 0 | *isNew = false; |
475 | 0 | return current; |
476 | 0 | } |
477 | 0 | parent = current; |
478 | 0 | current = (cmp < 0) ? current->left : current->right; |
479 | 0 | } |
480 | | |
481 | | /* |
482 | | * Value is not present, so create a new node containing data. |
483 | | */ |
484 | 0 | *isNew = true; |
485 | |
|
486 | 0 | x = rbt->allocfunc(rbt->arg); |
487 | |
|
488 | 0 | x->color = RBTRED; |
489 | |
|
490 | 0 | x->left = RBTNIL; |
491 | 0 | x->right = RBTNIL; |
492 | 0 | x->parent = parent; |
493 | 0 | rbt_copy_data(rbt, x, data); |
494 | | |
495 | | /* insert node in tree */ |
496 | 0 | if (parent) |
497 | 0 | { |
498 | 0 | if (cmp < 0) |
499 | 0 | parent->left = x; |
500 | 0 | else |
501 | 0 | parent->right = x; |
502 | 0 | } |
503 | 0 | else |
504 | 0 | { |
505 | 0 | rbt->root = x; |
506 | 0 | } |
507 | |
|
508 | 0 | rbt_insert_fixup(rbt, x); |
509 | |
|
510 | 0 | return x; |
511 | 0 | } |
512 | | |
513 | | /********************************************************************** |
514 | | * Deletion * |
515 | | **********************************************************************/ |
516 | | |
517 | | /* |
518 | | * Maintain Red-Black tree balance after deleting a black node. |
519 | | */ |
520 | | static void |
521 | | rbt_delete_fixup(RBTree *rbt, RBTNode *x) |
522 | 0 | { |
523 | | /* |
524 | | * x is always a black node. Initially, it is the former child of the |
525 | | * deleted node. Each iteration of this loop moves it higher up in the |
526 | | * tree. |
527 | | */ |
528 | 0 | while (x != rbt->root && x->color == RBTBLACK) |
529 | 0 | { |
530 | | /* |
531 | | * Left and right cases are symmetric. Any nodes that are children of |
532 | | * x have a black-height one less than the remainder of the nodes in |
533 | | * the tree. We rotate and recolor nodes to move the problem up the |
534 | | * tree: at some stage we'll either fix the problem, or reach the root |
535 | | * (where the black-height is allowed to decrease). |
536 | | */ |
537 | 0 | if (x == x->parent->left) |
538 | 0 | { |
539 | 0 | RBTNode *w = x->parent->right; |
540 | |
|
541 | 0 | if (w->color == RBTRED) |
542 | 0 | { |
543 | 0 | w->color = RBTBLACK; |
544 | 0 | x->parent->color = RBTRED; |
545 | |
|
546 | 0 | rbt_rotate_left(rbt, x->parent); |
547 | 0 | w = x->parent->right; |
548 | 0 | } |
549 | |
|
550 | 0 | if (w->left->color == RBTBLACK && w->right->color == RBTBLACK) |
551 | 0 | { |
552 | 0 | w->color = RBTRED; |
553 | |
|
554 | 0 | x = x->parent; |
555 | 0 | } |
556 | 0 | else |
557 | 0 | { |
558 | 0 | if (w->right->color == RBTBLACK) |
559 | 0 | { |
560 | 0 | w->left->color = RBTBLACK; |
561 | 0 | w->color = RBTRED; |
562 | |
|
563 | 0 | rbt_rotate_right(rbt, w); |
564 | 0 | w = x->parent->right; |
565 | 0 | } |
566 | 0 | w->color = x->parent->color; |
567 | 0 | x->parent->color = RBTBLACK; |
568 | 0 | w->right->color = RBTBLACK; |
569 | |
|
570 | 0 | rbt_rotate_left(rbt, x->parent); |
571 | 0 | x = rbt->root; /* Arrange for loop to terminate. */ |
572 | 0 | } |
573 | 0 | } |
574 | 0 | else |
575 | 0 | { |
576 | 0 | RBTNode *w = x->parent->left; |
577 | |
|
578 | 0 | if (w->color == RBTRED) |
579 | 0 | { |
580 | 0 | w->color = RBTBLACK; |
581 | 0 | x->parent->color = RBTRED; |
582 | |
|
583 | 0 | rbt_rotate_right(rbt, x->parent); |
584 | 0 | w = x->parent->left; |
585 | 0 | } |
586 | |
|
587 | 0 | if (w->right->color == RBTBLACK && w->left->color == RBTBLACK) |
588 | 0 | { |
589 | 0 | w->color = RBTRED; |
590 | |
|
591 | 0 | x = x->parent; |
592 | 0 | } |
593 | 0 | else |
594 | 0 | { |
595 | 0 | if (w->left->color == RBTBLACK) |
596 | 0 | { |
597 | 0 | w->right->color = RBTBLACK; |
598 | 0 | w->color = RBTRED; |
599 | |
|
600 | 0 | rbt_rotate_left(rbt, w); |
601 | 0 | w = x->parent->left; |
602 | 0 | } |
603 | 0 | w->color = x->parent->color; |
604 | 0 | x->parent->color = RBTBLACK; |
605 | 0 | w->left->color = RBTBLACK; |
606 | |
|
607 | 0 | rbt_rotate_right(rbt, x->parent); |
608 | 0 | x = rbt->root; /* Arrange for loop to terminate. */ |
609 | 0 | } |
610 | 0 | } |
611 | 0 | } |
612 | 0 | x->color = RBTBLACK; |
613 | 0 | } |
614 | | |
615 | | /* |
616 | | * Delete node z from tree. |
617 | | */ |
618 | | static void |
619 | | rbt_delete_node(RBTree *rbt, RBTNode *z) |
620 | 0 | { |
621 | 0 | RBTNode *x, |
622 | 0 | *y; |
623 | | |
624 | | /* This is just paranoia: we should only get called on a valid node */ |
625 | 0 | if (!z || z == RBTNIL) |
626 | 0 | return; |
627 | | |
628 | | /* |
629 | | * y is the node that will actually be removed from the tree. This will |
630 | | * be z if z has fewer than two children, or the tree successor of z |
631 | | * otherwise. |
632 | | */ |
633 | 0 | if (z->left == RBTNIL || z->right == RBTNIL) |
634 | 0 | { |
635 | | /* y has a RBTNIL node as a child */ |
636 | 0 | y = z; |
637 | 0 | } |
638 | 0 | else |
639 | 0 | { |
640 | | /* find tree successor */ |
641 | 0 | y = z->right; |
642 | 0 | while (y->left != RBTNIL) |
643 | 0 | y = y->left; |
644 | 0 | } |
645 | | |
646 | | /* x is y's only child */ |
647 | 0 | if (y->left != RBTNIL) |
648 | 0 | x = y->left; |
649 | 0 | else |
650 | 0 | x = y->right; |
651 | | |
652 | | /* Remove y from the tree. */ |
653 | 0 | x->parent = y->parent; |
654 | 0 | if (y->parent) |
655 | 0 | { |
656 | 0 | if (y == y->parent->left) |
657 | 0 | y->parent->left = x; |
658 | 0 | else |
659 | 0 | y->parent->right = x; |
660 | 0 | } |
661 | 0 | else |
662 | 0 | { |
663 | 0 | rbt->root = x; |
664 | 0 | } |
665 | | |
666 | | /* |
667 | | * If we removed the tree successor of z rather than z itself, then move |
668 | | * the data for the removed node to the one we were supposed to remove. |
669 | | */ |
670 | 0 | if (y != z) |
671 | 0 | rbt_copy_data(rbt, z, y); |
672 | | |
673 | | /* |
674 | | * Removing a black node might make some paths from root to leaf contain |
675 | | * fewer black nodes than others, or it might make two red nodes adjacent. |
676 | | */ |
677 | 0 | if (y->color == RBTBLACK) |
678 | 0 | rbt_delete_fixup(rbt, x); |
679 | | |
680 | | /* Now we can recycle the y node */ |
681 | 0 | if (rbt->freefunc) |
682 | 0 | rbt->freefunc(y, rbt->arg); |
683 | 0 | } |
684 | | |
685 | | /* |
686 | | * rbt_delete: remove the given tree entry |
687 | | * |
688 | | * "node" must have previously been found via rbt_find or rbt_leftmost. |
689 | | * It is caller's responsibility to free any subsidiary data attached |
690 | | * to the node before calling rbt_delete. (Do *not* try to push that |
691 | | * responsibility off to the freefunc, as some other physical node |
692 | | * may be the one actually freed!) |
693 | | */ |
694 | | void |
695 | | rbt_delete(RBTree *rbt, RBTNode *node) |
696 | 0 | { |
697 | 0 | rbt_delete_node(rbt, node); |
698 | 0 | } |
699 | | |
700 | | /********************************************************************** |
701 | | * Traverse * |
702 | | **********************************************************************/ |
703 | | |
704 | | static RBTNode * |
705 | | rbt_left_right_iterator(RBTreeIterator *iter) |
706 | 0 | { |
707 | 0 | if (iter->last_visited == NULL) |
708 | 0 | { |
709 | 0 | iter->last_visited = iter->rbt->root; |
710 | 0 | while (iter->last_visited->left != RBTNIL) |
711 | 0 | iter->last_visited = iter->last_visited->left; |
712 | |
|
713 | 0 | return iter->last_visited; |
714 | 0 | } |
715 | | |
716 | 0 | if (iter->last_visited->right != RBTNIL) |
717 | 0 | { |
718 | 0 | iter->last_visited = iter->last_visited->right; |
719 | 0 | while (iter->last_visited->left != RBTNIL) |
720 | 0 | iter->last_visited = iter->last_visited->left; |
721 | |
|
722 | 0 | return iter->last_visited; |
723 | 0 | } |
724 | | |
725 | 0 | for (;;) |
726 | 0 | { |
727 | 0 | RBTNode *came_from = iter->last_visited; |
728 | |
|
729 | 0 | iter->last_visited = iter->last_visited->parent; |
730 | 0 | if (iter->last_visited == NULL) |
731 | 0 | { |
732 | 0 | iter->is_over = true; |
733 | 0 | break; |
734 | 0 | } |
735 | | |
736 | 0 | if (iter->last_visited->left == came_from) |
737 | 0 | break; /* came from left sub-tree, return current |
738 | | * node */ |
739 | | |
740 | | /* else - came from right sub-tree, continue to move up */ |
741 | 0 | } |
742 | |
|
743 | 0 | return iter->last_visited; |
744 | 0 | } |
745 | | |
746 | | static RBTNode * |
747 | | rbt_right_left_iterator(RBTreeIterator *iter) |
748 | 0 | { |
749 | 0 | if (iter->last_visited == NULL) |
750 | 0 | { |
751 | 0 | iter->last_visited = iter->rbt->root; |
752 | 0 | while (iter->last_visited->right != RBTNIL) |
753 | 0 | iter->last_visited = iter->last_visited->right; |
754 | |
|
755 | 0 | return iter->last_visited; |
756 | 0 | } |
757 | | |
758 | 0 | if (iter->last_visited->left != RBTNIL) |
759 | 0 | { |
760 | 0 | iter->last_visited = iter->last_visited->left; |
761 | 0 | while (iter->last_visited->right != RBTNIL) |
762 | 0 | iter->last_visited = iter->last_visited->right; |
763 | |
|
764 | 0 | return iter->last_visited; |
765 | 0 | } |
766 | | |
767 | 0 | for (;;) |
768 | 0 | { |
769 | 0 | RBTNode *came_from = iter->last_visited; |
770 | |
|
771 | 0 | iter->last_visited = iter->last_visited->parent; |
772 | 0 | if (iter->last_visited == NULL) |
773 | 0 | { |
774 | 0 | iter->is_over = true; |
775 | 0 | break; |
776 | 0 | } |
777 | | |
778 | 0 | if (iter->last_visited->right == came_from) |
779 | 0 | break; /* came from right sub-tree, return current |
780 | | * node */ |
781 | | |
782 | | /* else - came from left sub-tree, continue to move up */ |
783 | 0 | } |
784 | |
|
785 | 0 | return iter->last_visited; |
786 | 0 | } |
787 | | |
788 | | /* |
789 | | * rbt_begin_iterate: prepare to traverse the tree in any of several orders |
790 | | * |
791 | | * After calling rbt_begin_iterate, call rbt_iterate repeatedly until it |
792 | | * returns NULL or the traversal stops being of interest. |
793 | | * |
794 | | * If the tree is changed during traversal, results of further calls to |
795 | | * rbt_iterate are unspecified. Multiple concurrent iterators on the same |
796 | | * tree are allowed. |
797 | | * |
798 | | * The iterator state is stored in the 'iter' struct. The caller should |
799 | | * treat it as an opaque struct. |
800 | | */ |
801 | | void |
802 | | rbt_begin_iterate(RBTree *rbt, RBTOrderControl ctrl, RBTreeIterator *iter) |
803 | 0 | { |
804 | | /* Common initialization for all traversal orders */ |
805 | 0 | iter->rbt = rbt; |
806 | 0 | iter->last_visited = NULL; |
807 | 0 | iter->is_over = (rbt->root == RBTNIL); |
808 | |
|
809 | 0 | switch (ctrl) |
810 | 0 | { |
811 | 0 | case LeftRightWalk: /* visit left, then self, then right */ |
812 | 0 | iter->iterate = rbt_left_right_iterator; |
813 | 0 | break; |
814 | 0 | case RightLeftWalk: /* visit right, then self, then left */ |
815 | 0 | iter->iterate = rbt_right_left_iterator; |
816 | 0 | break; |
817 | 0 | default: |
818 | 0 | elog(ERROR, "unrecognized rbtree iteration order: %d", ctrl); |
819 | 0 | } |
820 | 0 | } |
821 | | |
822 | | /* |
823 | | * rbt_iterate: return the next node in traversal order, or NULL if no more |
824 | | */ |
825 | | RBTNode * |
826 | | rbt_iterate(RBTreeIterator *iter) |
827 | 0 | { |
828 | 0 | if (iter->is_over) |
829 | 0 | return NULL; |
830 | | |
831 | 0 | return iter->iterate(iter); |
832 | 0 | } |