MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ut0rbt.cc
1 /***************************************************************************/
18 /********************************************************************/
26 #include "ut0rbt.h"
27 
28 /**********************************************************************/
47 #if defined(IB_RBT_TESTING)
48 #warning "Testing enabled!"
49 #endif
50 
51 #define ROOT(t) (t->root->left)
52 #define SIZEOF_NODE(t) ((sizeof(ib_rbt_node_t) + t->sizeof_value) - 1)
53 
54 /**********************************************************************/
56 static
57 void
58 rbt_print_subtree(
59 /*==============*/
60  const ib_rbt_t* tree,
61  const ib_rbt_node_t* node,
62  ib_rbt_print_node print)
63 {
64  /* FIXME: Doesn't do anything yet */
65  if (node != tree->nil) {
66  print(node);
67  rbt_print_subtree(tree, node->left, print);
68  rbt_print_subtree(tree, node->right, print);
69  }
70 }
71 
72 /**********************************************************************/
75 static
76 ibool
77 rbt_check_ordering(
78 /*===============*/
79  const ib_rbt_t* tree)
80 {
81  const ib_rbt_node_t* node;
82  const ib_rbt_node_t* prev = NULL;
83 
84  /* Iterate over all the nodes, comparing each node with the prev */
85  for (node = rbt_first(tree); node; node = rbt_next(tree, prev)) {
86 
87  if (prev) {
88  int result;
89 
90  if (tree->cmp_arg) {
91  result = tree->compare_with_arg(
92  tree->cmp_arg, prev->value,
93  node->value);
94  } else {
95  result = tree->compare(
96  prev->value, node->value);
97  }
98 
99  if (result >= 0) {
100  return(FALSE);
101  }
102  }
103 
104  prev = node;
105  }
106 
107  return(TRUE);
108 }
109 
110 /**********************************************************************/
114 static
115 ibool
116 rbt_count_black_nodes(
117 /*==================*/
118  const ib_rbt_t* tree,
119  const ib_rbt_node_t* node)
120 {
121  ulint result;
122 
123  if (node != tree->nil) {
124  ulint left_height = rbt_count_black_nodes(tree, node->left);
125 
126  ulint right_height = rbt_count_black_nodes(tree, node->right);
127 
128  if (left_height == 0
129  || right_height == 0
130  || left_height != right_height) {
131 
132  result = 0;
133  } else if (node->color == IB_RBT_RED) {
134 
135  /* Case 3 */
136  if (node->left->color != IB_RBT_BLACK
137  || node->right->color != IB_RBT_BLACK) {
138 
139  result = 0;
140  } else {
141  result = left_height;
142  }
143  /* Check if it's anything other than RED or BLACK. */
144  } else if (node->color != IB_RBT_BLACK) {
145 
146  result = 0;
147  } else {
148 
149  result = right_height + 1;
150  }
151  } else {
152  result = 1;
153  }
154 
155  return(result);
156 }
157 
158 /**********************************************************************/
161 static
162 void
163 rbt_rotate_left(
164 /*============*/
165  const ib_rbt_node_t* nil,
166  ib_rbt_node_t* node)
167 {
168  ib_rbt_node_t* right = node->right;
169 
170  node->right = right->left;
171 
172  if (right->left != nil) {
173  right->left->parent = node;
174  }
175 
176  /* Right's new parent was node's parent. */
177  right->parent = node->parent;
178 
179  /* Since root's parent is tree->nil and root->parent->left points
180  back to root, we can avoid the check. */
181  if (node == node->parent->left) {
182  /* Node was on the left of its parent. */
183  node->parent->left = right;
184  } else {
185  /* Node must have been on the right. */
186  node->parent->right = right;
187  }
188 
189  /* Finally, put node on right's left. */
190  right->left = node;
191  node->parent = right;
192 }
193 
194 /**********************************************************************/
197 static
198 void
199 rbt_rotate_right(
200 /*=============*/
201  const ib_rbt_node_t* nil,
202  ib_rbt_node_t* node)
203 {
204  ib_rbt_node_t* left = node->left;
205 
206  node->left = left->right;
207 
208  if (left->right != nil) {
209  left->right->parent = node;
210  }
211 
212  /* Left's new parent was node's parent. */
213  left->parent = node->parent;
214 
215  /* Since root's parent is tree->nil and root->parent->left points
216  back to root, we can avoid the check. */
217  if (node == node->parent->right) {
218  /* Node was on the left of its parent. */
219  node->parent->right = left;
220  } else {
221  /* Node must have been on the left. */
222  node->parent->left = left;
223  }
224 
225  /* Finally, put node on left's right. */
226  left->right = node;
227  node->parent = left;
228 }
229 
230 /**********************************************************************/
232 static
234 rbt_tree_add_child(
235 /*===============*/
236  const ib_rbt_t* tree,
237  ib_rbt_bound_t* parent,
238  ib_rbt_node_t* node)
239 {
240  /* Cast away the const. */
241  ib_rbt_node_t* last = (ib_rbt_node_t*) parent->last;
242 
243  if (last == tree->root || parent->result < 0) {
244  last->left = node;
245  } else {
246  /* FIXME: We don't handle duplicates (yet)! */
247  ut_a(parent->result != 0);
248 
249  last->right = node;
250  }
251 
252  node->parent = last;
253 
254  return(node);
255 }
256 
257 /**********************************************************************/
259 static
261 rbt_tree_insert(
262 /*============*/
263  ib_rbt_t* tree,
264  const void* key,
265  ib_rbt_node_t* node)
266 {
267  ib_rbt_bound_t parent;
268  ib_rbt_node_t* current = ROOT(tree);
269 
270  parent.result = 0;
271  parent.last = tree->root;
272 
273  /* Regular binary search. */
274  while (current != tree->nil) {
275 
276  parent.last = current;
277 
278  if (tree->cmp_arg) {
279  parent.result = tree->compare_with_arg(
280  tree->cmp_arg, key, current->value);
281  } else {
282  parent.result = tree->compare(key, current->value);
283  }
284 
285  if (parent.result < 0) {
286  current = current->left;
287  } else {
288  current = current->right;
289  }
290  }
291 
292  ut_a(current == tree->nil);
293 
294  rbt_tree_add_child(tree, &parent, node);
295 
296  return(node);
297 }
298 
299 /**********************************************************************/
301 static
302 void
303 rbt_balance_tree(
304 /*=============*/
305  const ib_rbt_t* tree,
306  ib_rbt_node_t* node)
307 {
308  const ib_rbt_node_t* nil = tree->nil;
309  ib_rbt_node_t* parent = node->parent;
310 
311  /* Restore the red-black property. */
312  node->color = IB_RBT_RED;
313 
314  while (node != ROOT(tree) && parent->color == IB_RBT_RED) {
315  ib_rbt_node_t* grand_parent = parent->parent;
316 
317  if (parent == grand_parent->left) {
318  ib_rbt_node_t* uncle = grand_parent->right;
319 
320  if (uncle->color == IB_RBT_RED) {
321 
322  /* Case 1 - change the colors. */
323  uncle->color = IB_RBT_BLACK;
324  parent->color = IB_RBT_BLACK;
325  grand_parent->color = IB_RBT_RED;
326 
327  /* Move node up the tree. */
328  node = grand_parent;
329 
330  } else {
331 
332  if (node == parent->right) {
333  /* Right is a black node and node is
334  to the right, case 2 - move node
335  up and rotate. */
336  node = parent;
337  rbt_rotate_left(nil, node);
338  }
339 
340  grand_parent = node->parent->parent;
341 
342  /* Case 3. */
343  node->parent->color = IB_RBT_BLACK;
344  grand_parent->color = IB_RBT_RED;
345 
346  rbt_rotate_right(nil, grand_parent);
347  }
348 
349  } else {
350  ib_rbt_node_t* uncle = grand_parent->left;
351 
352  if (uncle->color == IB_RBT_RED) {
353 
354  /* Case 1 - change the colors. */
355  uncle->color = IB_RBT_BLACK;
356  parent->color = IB_RBT_BLACK;
357  grand_parent->color = IB_RBT_RED;
358 
359  /* Move node up the tree. */
360  node = grand_parent;
361 
362  } else {
363 
364  if (node == parent->left) {
365  /* Left is a black node and node is to
366  the right, case 2 - move node up and
367  rotate. */
368  node = parent;
369  rbt_rotate_right(nil, node);
370  }
371 
372  grand_parent = node->parent->parent;
373 
374  /* Case 3. */
375  node->parent->color = IB_RBT_BLACK;
376  grand_parent->color = IB_RBT_RED;
377 
378  rbt_rotate_left(nil, grand_parent);
379  }
380  }
381 
382  parent = node->parent;
383  }
384 
385  /* Color the root black. */
386  ROOT(tree)->color = IB_RBT_BLACK;
387 }
388 
389 /**********************************************************************/
392 static
394 rbt_find_successor(
395 /*===============*/
396  const ib_rbt_t* tree,
397  const ib_rbt_node_t* current)
400 {
401  const ib_rbt_node_t* nil = tree->nil;
402  ib_rbt_node_t* next = current->right;
403 
404  /* Is there a sub-tree to the right that we can follow. */
405  if (next != nil) {
406 
407  /* Follow the left most links of the current right child. */
408  while (next->left != nil) {
409  next = next->left;
410  }
411 
412  } else { /* We will have to go up the tree to find the successor. */
413  ib_rbt_node_t* parent = current->parent;
414 
415  /* Cast away the const. */
416  next = (ib_rbt_node_t*) current;
417 
418  while (parent != tree->root && next == parent->right) {
419  next = parent;
420  parent = next->parent;
421  }
422 
423  next = (parent == tree->root) ? NULL : parent;
424  }
425 
426  return(next);
427 }
428 
429 /**********************************************************************/
432 static
434 rbt_find_predecessor(
435 /*=================*/
436  const ib_rbt_t* tree,
437  const ib_rbt_node_t* current)
440 {
441  const ib_rbt_node_t* nil = tree->nil;
442  ib_rbt_node_t* prev = current->left;
443 
444  /* Is there a sub-tree to the left that we can follow. */
445  if (prev != nil) {
446 
447  /* Follow the right most links of the current left child. */
448  while (prev->right != nil) {
449  prev = prev->right;
450  }
451 
452  } else { /* We will have to go up the tree to find the precedecessor. */
453  ib_rbt_node_t* parent = current->parent;
454 
455  /* Cast away the const. */
456  prev = (ib_rbt_node_t*) current;
457 
458  while (parent != tree->root && prev == parent->left) {
459  prev = parent;
460  parent = prev->parent;
461  }
462 
463  prev = (parent == tree->root) ? NULL : parent;
464  }
465 
466  return(prev);
467 }
468 
469 /**********************************************************************/
472 static
473 void
474 rbt_eject_node(
475 /*===========*/
476  ib_rbt_node_t* eject,
477  ib_rbt_node_t* node)
478 {
479  /* Update the to be ejected node's parent's child pointers. */
480  if (eject->parent->left == eject) {
481  eject->parent->left = node;
482  } else if (eject->parent->right == eject) {
483  eject->parent->right = node;
484  } else {
485  ut_a(0);
486  }
487  /* eject is now an orphan but otherwise its pointers
488  and color are left intact. */
489 
490  node->parent = eject->parent;
491 }
492 
493 /**********************************************************************/
495 static
496 void
497 rbt_replace_node(
498 /*=============*/
500  ib_rbt_node_t* node)
501 {
502  ib_rbt_color_t color = node->color;
503 
504  /* Update the node pointers. */
505  node->left = replace->left;
506  node->right = replace->right;
507 
508  /* Update the child node pointers. */
509  node->left->parent = node;
510  node->right->parent = node;
511 
512  /* Make the parent of replace point to node. */
513  rbt_eject_node(replace, node);
514 
515  /* Swap the colors. */
516  node->color = replace->color;
517  replace->color = color;
518 }
519 
520 /**********************************************************************/
523 static
525 rbt_detach_node(
526 /*============*/
527  const ib_rbt_t* tree,
528  ib_rbt_node_t* node)
529 {
530  ib_rbt_node_t* child;
531  const ib_rbt_node_t* nil = tree->nil;
532 
533  if (node->left != nil && node->right != nil) {
534  /* Case where the node to be deleted has two children. */
535  ib_rbt_node_t* successor = rbt_find_successor(tree, node);
536 
537  ut_a(successor != nil);
538  ut_a(successor->parent != nil);
539  ut_a(successor->left == nil);
540 
541  child = successor->right;
542 
543  /* Remove the successor node and replace with its child. */
544  rbt_eject_node(successor, child);
545 
546  /* Replace the node to delete with its successor node. */
547  rbt_replace_node(node, successor);
548  } else {
549  ut_a(node->left == nil || node->right == nil);
550 
551  child = (node->left != nil) ? node->left : node->right;
552 
553  /* Replace the node to delete with one of it's children. */
554  rbt_eject_node(node, child);
555  }
556 
557  /* Reset the node links. */
558  node->parent = node->right = node->left = tree->nil;
559 
560  return(child);
561 }
562 
563 /**********************************************************************/
566 static
568 rbt_balance_right(
569 /*==============*/
570  const ib_rbt_node_t* nil,
571  ib_rbt_node_t* parent,
572  ib_rbt_node_t* sibling)
573 {
574  ib_rbt_node_t* node = NULL;
575 
576  ut_a(sibling != nil);
577 
578  /* Case 3. */
579  if (sibling->color == IB_RBT_RED) {
580 
581  parent->color = IB_RBT_RED;
582  sibling->color = IB_RBT_BLACK;
583 
584  rbt_rotate_left(nil, parent);
585 
586  sibling = parent->right;
587 
588  ut_a(sibling != nil);
589  }
590 
591  /* Since this will violate case 3 because of the change above. */
592  if (sibling->left->color == IB_RBT_BLACK
593  && sibling->right->color == IB_RBT_BLACK) {
594 
595  node = parent; /* Parent needs to be rebalanced too. */
596  sibling->color = IB_RBT_RED;
597 
598  } else {
599  if (sibling->right->color == IB_RBT_BLACK) {
600 
601  ut_a(sibling->left->color == IB_RBT_RED);
602 
603  sibling->color = IB_RBT_RED;
604  sibling->left->color = IB_RBT_BLACK;
605 
606  rbt_rotate_right(nil, sibling);
607 
608  sibling = parent->right;
609  ut_a(sibling != nil);
610  }
611 
612  sibling->color = parent->color;
613  sibling->right->color = IB_RBT_BLACK;
614 
615  parent->color = IB_RBT_BLACK;
616 
617  rbt_rotate_left(nil, parent);
618  }
619 
620  return(node);
621 }
622 
623 /**********************************************************************/
626 static
628 rbt_balance_left(
629 /*=============*/
630  const ib_rbt_node_t* nil,
631  ib_rbt_node_t* parent,
632  ib_rbt_node_t* sibling)
633 {
634  ib_rbt_node_t* node = NULL;
635 
636  ut_a(sibling != nil);
637 
638  /* Case 3. */
639  if (sibling->color == IB_RBT_RED) {
640 
641  parent->color = IB_RBT_RED;
642  sibling->color = IB_RBT_BLACK;
643 
644  rbt_rotate_right(nil, parent);
645  sibling = parent->left;
646 
647  ut_a(sibling != nil);
648  }
649 
650  /* Since this will violate case 3 because of the change above. */
651  if (sibling->right->color == IB_RBT_BLACK
652  && sibling->left->color == IB_RBT_BLACK) {
653 
654  node = parent; /* Parent needs to be rebalanced too. */
655  sibling->color = IB_RBT_RED;
656 
657  } else {
658  if (sibling->left->color == IB_RBT_BLACK) {
659 
660  ut_a(sibling->right->color == IB_RBT_RED);
661 
662  sibling->color = IB_RBT_RED;
663  sibling->right->color = IB_RBT_BLACK;
664 
665  rbt_rotate_left(nil, sibling);
666 
667  sibling = parent->left;
668 
669  ut_a(sibling != nil);
670  }
671 
672  sibling->color = parent->color;
673  sibling->left->color = IB_RBT_BLACK;
674 
675  parent->color = IB_RBT_BLACK;
676 
677  rbt_rotate_right(nil, parent);
678  }
679 
680  return(node);
681 }
682 
683 /**********************************************************************/
685 static
686 void
687 rbt_remove_node_and_rebalance(
688 /*==========================*/
689  ib_rbt_t* tree,
690  ib_rbt_node_t* node)
691 {
692  /* Detach node and get the node that will be used
693  as rebalance start. */
694  ib_rbt_node_t* child = rbt_detach_node(tree, node);
695 
696  if (node->color == IB_RBT_BLACK) {
697  ib_rbt_node_t* last = child;
698 
699  ROOT(tree)->color = IB_RBT_RED;
700 
701  while (child && child->color == IB_RBT_BLACK) {
702  ib_rbt_node_t* parent = child->parent;
703 
704  /* Did the deletion cause an imbalance in the
705  parents left sub-tree. */
706  if (parent->left == child) {
707 
708  child = rbt_balance_right(
709  tree->nil, parent, parent->right);
710 
711  } else if (parent->right == child) {
712 
713  child = rbt_balance_left(
714  tree->nil, parent, parent->left);
715 
716  } else {
717  ut_error;
718  }
719 
720  if (child) {
721  last = child;
722  }
723  }
724 
725  ut_a(last);
726 
727  last->color = IB_RBT_BLACK;
728  ROOT(tree)->color = IB_RBT_BLACK;
729  }
730 
731  /* Note that we have removed a node from the tree. */
732  --tree->n_nodes;
733 }
734 
735 /**********************************************************************/
737 static
738 void
739 rbt_free_node(
740 /*==========*/
741  ib_rbt_node_t* node,
742  ib_rbt_node_t* nil)
743 {
744  if (node != nil) {
745  rbt_free_node(node->left, nil);
746  rbt_free_node(node->right, nil);
747 
748  ut_free(node);
749  }
750 }
751 
752 /**********************************************************************/
754 UNIV_INTERN
755 void
757 /*=====*/
758  ib_rbt_t* tree)
759 {
760  rbt_free_node(tree->root, tree->nil);
761  ut_free(tree->nil);
762  ut_free(tree);
763 }
764 
765 /**********************************************************************/
769 UNIV_INTERN
770 ib_rbt_t*
772 /*===============*/
773  size_t sizeof_value,
774  ib_rbt_arg_compare
775  compare,
776  void* cmp_arg)
777 {
778  ib_rbt_t* tree;
779 
780  ut_a(cmp_arg);
781 
782  tree = rbt_create(sizeof_value, NULL);
783  tree->cmp_arg = cmp_arg;
784  tree->compare_with_arg = compare;
785 
786  return(tree);
787 }
788 
789 /**********************************************************************/
792 UNIV_INTERN
793 ib_rbt_t*
795 /*=======*/
796  size_t sizeof_value,
797  ib_rbt_compare compare)
798 {
799  ib_rbt_t* tree;
800  ib_rbt_node_t* node;
801 
802  tree = (ib_rbt_t*) ut_malloc(sizeof(*tree));
803  memset(tree, 0, sizeof(*tree));
804 
805  tree->sizeof_value = sizeof_value;
806 
807  /* Create the sentinel (NIL) node. */
808  node = tree->nil = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
809  memset(node, 0, sizeof(*node));
810 
811  node->color = IB_RBT_BLACK;
812  node->parent = node->left = node->right = node;
813 
814  /* Create the "fake" root, the real root node will be the
815  left child of this node. */
816  node = tree->root = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
817  memset(node, 0, sizeof(*node));
818 
819  node->color = IB_RBT_BLACK;
820  node->parent = node->left = node->right = tree->nil;
821 
822  tree->compare = compare;
823 
824  return(tree);
825 }
826 
827 /**********************************************************************/
830 UNIV_INTERN
831 const ib_rbt_node_t*
833 /*=======*/
834  ib_rbt_t* tree,
835  const void* key,
836  const void* value)
838 {
839  ib_rbt_node_t* node;
840 
841  /* Create the node that will hold the value data. */
842  node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));
843 
844  memcpy(node->value, value, tree->sizeof_value);
845  node->parent = node->left = node->right = tree->nil;
846 
847  /* Insert in the tree in the usual way. */
848  rbt_tree_insert(tree, key, node);
849  rbt_balance_tree(tree, node);
850 
851  ++tree->n_nodes;
852 
853  return(node);
854 }
855 
856 /**********************************************************************/
859 UNIV_INTERN
860 const ib_rbt_node_t*
862 /*=========*/
863  ib_rbt_t* tree,
864  ib_rbt_bound_t* parent,
865  const void* value)
867 {
868  ib_rbt_node_t* node;
869 
870  /* Create the node that will hold the value data */
871  node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree));
872 
873  memcpy(node->value, value, tree->sizeof_value);
874  node->parent = node->left = node->right = tree->nil;
875 
876  /* If tree is empty */
877  if (parent->last == NULL) {
878  parent->last = tree->root;
879  }
880 
881  /* Append the node, the hope here is that the caller knows
882  what s/he is doing. */
883  rbt_tree_add_child(tree, parent, node);
884  rbt_balance_tree(tree, node);
885 
886  ++tree->n_nodes;
887 
888 #if defined(IB_RBT_TESTING)
889  ut_a(rbt_validate(tree));
890 #endif
891  return(node);
892 }
893 
894 /**********************************************************************/
897 UNIV_INTERN
898 const ib_rbt_node_t*
900 /*=======*/
901  const ib_rbt_t* tree,
902  const void* key)
903 {
904  const ib_rbt_node_t* current = ROOT(tree);
905 
906  /* Regular binary search. */
907  while (current != tree->nil) {
908  int result;
909 
910  if (tree->cmp_arg) {
911  result = tree->compare_with_arg(
912  tree->cmp_arg, key, current->value);
913  } else {
914  result = tree->compare(key, current->value);
915  }
916 
917  if (result < 0) {
918  current = current->left;
919  } else if (result > 0) {
920  current = current->right;
921  } else {
922  break;
923  }
924  }
925 
926  return(current != tree->nil ? current : NULL);
927 }
928 
929 /**********************************************************************/
932 UNIV_INTERN
933 ibool
935 /*=======*/
936  ib_rbt_t* tree,
937  const void* key)
938 {
939  ibool deleted = FALSE;
940  ib_rbt_node_t* node = (ib_rbt_node_t*) rbt_lookup(tree, key);
941 
942  if (node) {
943  rbt_remove_node_and_rebalance(tree, node);
944 
945  ut_free(node);
946  deleted = TRUE;
947  }
948 
949  return(deleted);
950 }
951 
952 /**********************************************************************/
956 UNIV_INTERN
959 /*============*/
960  ib_rbt_t* tree,
961  const ib_rbt_node_t* const_node)
965 {
966  /* Cast away the const. */
967  rbt_remove_node_and_rebalance(tree, (ib_rbt_node_t*) const_node);
968 
969  /* This is to make it easier to do something like this:
970  ut_free(rbt_remove_node(node));
971  */
972 
973  return((ib_rbt_node_t*) const_node);
974 }
975 
976 /**********************************************************************/
979 UNIV_INTERN
980 const ib_rbt_node_t*
982 /*============*/
983  const ib_rbt_t* tree,
984  const void* key)
985 {
986  ib_rbt_node_t* lb_node = NULL;
987  ib_rbt_node_t* current = ROOT(tree);
988 
989  while (current != tree->nil) {
990  int result;
991 
992  if (tree->cmp_arg) {
993  result = tree->compare_with_arg(
994  tree->cmp_arg, key, current->value);
995  } else {
996  result = tree->compare(key, current->value);
997  }
998 
999  if (result > 0) {
1000 
1001  current = current->right;
1002 
1003  } else if (result < 0) {
1004 
1005  lb_node = current;
1006  current = current->left;
1007 
1008  } else {
1009  lb_node = current;
1010  break;
1011  }
1012  }
1013 
1014  return(lb_node);
1015 }
1016 
1017 /**********************************************************************/
1020 UNIV_INTERN
1021 const ib_rbt_node_t*
1023 /*============*/
1024  const ib_rbt_t* tree,
1025  const void* key)
1026 {
1027  ib_rbt_node_t* ub_node = NULL;
1028  ib_rbt_node_t* current = ROOT(tree);
1029 
1030  while (current != tree->nil) {
1031  int result;
1032 
1033  if (tree->cmp_arg) {
1034  result = tree->compare_with_arg(
1035  tree->cmp_arg, key, current->value);
1036  } else {
1037  result = tree->compare(key, current->value);
1038  }
1039 
1040  if (result > 0) {
1041 
1042  ub_node = current;
1043  current = current->right;
1044 
1045  } else if (result < 0) {
1046 
1047  current = current->left;
1048 
1049  } else {
1050  ub_node = current;
1051  break;
1052  }
1053  }
1054 
1055  return(ub_node);
1056 }
1057 
1058 /**********************************************************************/
1061 UNIV_INTERN
1062 int
1064 /*=======*/
1065  const ib_rbt_t* tree,
1066  ib_rbt_bound_t* parent,
1067  const void* key)
1068 {
1069  ib_rbt_node_t* current = ROOT(tree);
1070 
1071  /* Every thing is greater than the NULL root. */
1072  parent->result = 1;
1073  parent->last = NULL;
1074 
1075  while (current != tree->nil) {
1076 
1077  parent->last = current;
1078 
1079  if (tree->cmp_arg) {
1080  parent->result = tree->compare_with_arg(
1081  tree->cmp_arg, key, current->value);
1082  } else {
1083  parent->result = tree->compare(key, current->value);
1084  }
1085 
1086  if (parent->result > 0) {
1087  current = current->right;
1088  } else if (parent->result < 0) {
1089  current = current->left;
1090  } else {
1091  break;
1092  }
1093  }
1094 
1095  return(parent->result);
1096 }
1097 
1098 /**********************************************************************/
1102 UNIV_INTERN
1103 int
1105 /*===========*/
1106  const ib_rbt_t* tree,
1107  ib_rbt_bound_t* parent,
1108  const void* key,
1109  ib_rbt_compare compare,
1110  ib_rbt_arg_compare
1111  arg_compare)
1113 {
1114  ib_rbt_node_t* current = ROOT(tree);
1115 
1116  /* Every thing is greater than the NULL root. */
1117  parent->result = 1;
1118  parent->last = NULL;
1119 
1120  while (current != tree->nil) {
1121 
1122  parent->last = current;
1123 
1124  if (arg_compare) {
1125  ut_ad(tree->cmp_arg);
1126  parent->result = arg_compare(
1127  tree->cmp_arg, key, current->value);
1128  } else {
1129  parent->result = compare(key, current->value);
1130  }
1131 
1132  if (parent->result > 0) {
1133  current = current->right;
1134  } else if (parent->result < 0) {
1135  current = current->left;
1136  } else {
1137  break;
1138  }
1139  }
1140 
1141  return(parent->result);
1142 }
1143 
1144 /**********************************************************************/
1146 UNIV_INTERN
1147 const ib_rbt_node_t*
1149 /*======*/
1150  /* out leftmost node or NULL */
1151  const ib_rbt_t* tree) /* in: rb tree */
1152 {
1153  ib_rbt_node_t* first = NULL;
1154  ib_rbt_node_t* current = ROOT(tree);
1155 
1156  while (current != tree->nil) {
1157  first = current;
1158  current = current->left;
1159  }
1160 
1161  return(first);
1162 }
1163 
1164 /**********************************************************************/
1167 UNIV_INTERN
1168 const ib_rbt_node_t*
1170 /*=====*/
1171  const ib_rbt_t* tree)
1172 {
1173  ib_rbt_node_t* last = NULL;
1174  ib_rbt_node_t* current = ROOT(tree);
1175 
1176  while (current != tree->nil) {
1177  last = current;
1178  current = current->right;
1179  }
1180 
1181  return(last);
1182 }
1183 
1184 /**********************************************************************/
1187 UNIV_INTERN
1188 const ib_rbt_node_t*
1190 /*=====*/
1191  const ib_rbt_t* tree,
1192  const ib_rbt_node_t* current)
1193 {
1194  return(current ? rbt_find_successor(tree, current) : NULL);
1195 }
1196 
1197 /**********************************************************************/
1200 UNIV_INTERN
1201 const ib_rbt_node_t*
1203 /*=====*/
1204  const ib_rbt_t* tree,
1205  const ib_rbt_node_t* current)
1206 {
1207  return(current ? rbt_find_predecessor(tree, current) : NULL);
1208 }
1209 
1210 /**********************************************************************/
1212 UNIV_INTERN
1213 void
1215 /*======*/
1216  ib_rbt_t* tree)
1217 {
1218  rbt_free_node(ROOT(tree), tree->nil);
1219 
1220  tree->n_nodes = 0;
1221  tree->root->left = tree->root->right = tree->nil;
1222 }
1223 
1224 /**********************************************************************/
1227 UNIV_INTERN
1228 ulint
1230 /*===========*/
1231  ib_rbt_t* dst,
1232  const ib_rbt_t* src)
1233 {
1234  ib_rbt_bound_t parent;
1235  ulint n_merged = 0;
1236  const ib_rbt_node_t* src_node = rbt_first(src);
1237 
1238  if (rbt_empty(src) || dst == src) {
1239  return(0);
1240  }
1241 
1242  for (/* No op */; src_node; src_node = rbt_next(src, src_node)) {
1243 
1244  if (rbt_search(dst, &parent, src_node->value) != 0) {
1245  rbt_add_node(dst, &parent, src_node->value);
1246  ++n_merged;
1247  }
1248  }
1249 
1250  return(n_merged);
1251 }
1252 
1253 /**********************************************************************/
1258 UNIV_INTERN
1259 ulint
1261 /*=======================*/
1262  ib_rbt_t* dst,
1263  ib_rbt_t* src)
1264 {
1265  ib_rbt_bound_t parent;
1266  ib_rbt_node_t* src_node;
1267  ulint old_size = rbt_size(dst);
1268 
1269  if (rbt_empty(src) || dst == src) {
1270  return(0);
1271  }
1272 
1273  for (src_node = (ib_rbt_node_t*) rbt_first(src); src_node; /* */) {
1274  ib_rbt_node_t* prev = src_node;
1275 
1276  src_node = (ib_rbt_node_t*) rbt_next(src, prev);
1277 
1278  /* Skip duplicates. */
1279  if (rbt_search(dst, &parent, prev->value) != 0) {
1280 
1281  /* Remove and reset the node but preserve
1282  the node (data) value. */
1283  rbt_remove_node_and_rebalance(src, prev);
1284 
1285  /* The nil should be taken from the dst tree. */
1286  prev->parent = prev->left = prev->right = dst->nil;
1287  rbt_tree_add_child(dst, &parent, prev);
1288  rbt_balance_tree(dst, prev);
1289 
1290  ++dst->n_nodes;
1291  }
1292  }
1293 
1294 #if defined(IB_RBT_TESTING)
1295  ut_a(rbt_validate(dst));
1296  ut_a(rbt_validate(src));
1297 #endif
1298  return(rbt_size(dst) - old_size);
1299 }
1300 
1301 /**********************************************************************/
1305 UNIV_INTERN
1306 ibool
1308 /*=========*/
1309  const ib_rbt_t* tree)
1310 {
1311  if (rbt_count_black_nodes(tree, ROOT(tree)) > 0) {
1312  return(rbt_check_ordering(tree));
1313  }
1314 
1315  return(FALSE);
1316 }
1317 
1318 /**********************************************************************/
1320 UNIV_INTERN
1321 void
1323 /*======*/
1324  const ib_rbt_t* tree,
1325  ib_rbt_print_node print)
1326 {
1327  rbt_print_subtree(tree, ROOT(tree), print);
1328 }