1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_OPERATIONS --
9 -- Copyright (C) 2004-2017, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 -- The references below to "CLR" refer to the following book, from which
31 -- several of the algorithms here were adapted:
32 -- Introduction to Algorithms
33 -- by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest
34 -- Publisher: The MIT Press (June 18, 1990)
37 with System
; use type System
.Address
;
39 package body Ada
.Containers
.Red_Black_Trees
.Generic_Operations
is
41 pragma Warnings
(Off
, "variable ""Busy*"" is not referenced");
42 pragma Warnings
(Off
, "variable ""Lock*"" is not referenced");
43 -- See comment in Ada.Containers.Helpers
45 -----------------------
46 -- Local Subprograms --
47 -----------------------
49 procedure Delete_Fixup
(Tree
: in out Tree_Type
; Node
: Node_Access
);
51 procedure Delete_Swap
(Tree
: in out Tree_Type
; Z
, Y
: Node_Access
);
53 procedure Left_Rotate
(Tree
: in out Tree_Type
; X
: Node_Access
);
54 procedure Right_Rotate
(Tree
: in out Tree_Type
; Y
: Node_Access
);
56 -- Why is all the following code commented out ???
58 -- ---------------------
59 -- -- Check_Invariant --
60 -- ---------------------
62 -- procedure Check_Invariant (Tree : Tree_Type) is
63 -- Root : constant Node_Access := Tree.Root;
65 -- function Check (Node : Node_Access) return Natural;
71 -- function Check (Node : Node_Access) return Natural is
73 -- if Node = null then
77 -- if Color (Node) = Red then
79 -- L : constant Node_Access := Left (Node);
81 -- pragma Assert (L = null or else Color (L) = Black);
86 -- R : constant Node_Access := Right (Node);
88 -- pragma Assert (R = null or else Color (R) = Black);
93 -- NL : constant Natural := Check (Left (Node));
94 -- NR : constant Natural := Check (Right (Node));
96 -- pragma Assert (NL = NR);
102 -- NL : constant Natural := Check (Left (Node));
103 -- NR : constant Natural := Check (Right (Node));
105 -- pragma Assert (NL = NR);
110 -- -- Start of processing for Check_Invariant
113 -- if Root = null then
114 -- pragma Assert (Tree.First = null);
115 -- pragma Assert (Tree.Last = null);
116 -- pragma Assert (Tree.Length = 0);
120 -- pragma Assert (Color (Root) = Black);
121 -- pragma Assert (Tree.Length > 0);
122 -- pragma Assert (Tree.Root /= null);
123 -- pragma Assert (Tree.First /= null);
124 -- pragma Assert (Tree.Last /= null);
125 -- pragma Assert (Parent (Tree.Root) = null);
126 -- pragma Assert ((Tree.Length > 1)
127 -- or else (Tree.First = Tree.Last
128 -- and Tree.First = Tree.Root));
129 -- pragma Assert (Left (Tree.First) = null);
130 -- pragma Assert (Right (Tree.Last) = null);
133 -- L : constant Node_Access := Left (Root);
134 -- R : constant Node_Access := Right (Root);
135 -- NL : constant Natural := Check (L);
136 -- NR : constant Natural := Check (R);
138 -- pragma Assert (NL = NR);
142 -- end Check_Invariant;
148 procedure Delete_Fixup
(Tree
: in out Tree_Type
; Node
: Node_Access
) is
152 X
: Node_Access
:= Node
;
157 and then Color
(X
) = Black
159 if X
= Left
(Parent
(X
)) then
160 W
:= Right
(Parent
(X
));
162 if Color
(W
) = Red
then
163 Set_Color
(W
, Black
);
164 Set_Color
(Parent
(X
), Red
);
165 Left_Rotate
(Tree
, Parent
(X
));
166 W
:= Right
(Parent
(X
));
169 if (Left
(W
) = null or else Color
(Left
(W
)) = Black
)
171 (Right
(W
) = null or else Color
(Right
(W
)) = Black
)
178 or else Color
(Right
(W
)) = Black
180 -- As a condition for setting the color of the left child to
181 -- black, the left child access value must be non-null. A
182 -- truth table analysis shows that if we arrive here, that
183 -- condition holds, so there's no need for an explicit test.
184 -- The assertion is here to document what we know is true.
186 pragma Assert
(Left
(W
) /= null);
187 Set_Color
(Left
(W
), Black
);
190 Right_Rotate
(Tree
, W
);
191 W
:= Right
(Parent
(X
));
194 Set_Color
(W
, Color
(Parent
(X
)));
195 Set_Color
(Parent
(X
), Black
);
196 Set_Color
(Right
(W
), Black
);
197 Left_Rotate
(Tree
, Parent
(X
));
202 pragma Assert
(X
= Right
(Parent
(X
)));
204 W
:= Left
(Parent
(X
));
206 if Color
(W
) = Red
then
207 Set_Color
(W
, Black
);
208 Set_Color
(Parent
(X
), Red
);
209 Right_Rotate
(Tree
, Parent
(X
));
210 W
:= Left
(Parent
(X
));
213 if (Left
(W
) = null or else Color
(Left
(W
)) = Black
)
215 (Right
(W
) = null or else Color
(Right
(W
)) = Black
)
221 if Left
(W
) = null or else Color
(Left
(W
)) = Black
then
223 -- As a condition for setting the color of the right child
224 -- to black, the right child access value must be non-null.
225 -- A truth table analysis shows that if we arrive here, that
226 -- condition holds, so there's no need for an explicit test.
227 -- The assertion is here to document what we know is true.
229 pragma Assert
(Right
(W
) /= null);
230 Set_Color
(Right
(W
), Black
);
233 Left_Rotate
(Tree
, W
);
234 W
:= Left
(Parent
(X
));
237 Set_Color
(W
, Color
(Parent
(X
)));
238 Set_Color
(Parent
(X
), Black
);
239 Set_Color
(Left
(W
), Black
);
240 Right_Rotate
(Tree
, Parent
(X
));
246 Set_Color
(X
, Black
);
249 ---------------------------
250 -- Delete_Node_Sans_Free --
251 ---------------------------
253 procedure Delete_Node_Sans_Free
254 (Tree
: in out Tree_Type
;
261 Z
: constant Node_Access
:= Node
;
262 pragma Assert
(Z
/= null);
267 -- Why are these all commented out ???
269 -- pragma Assert (Tree.Length > 0);
270 -- pragma Assert (Tree.Root /= null);
271 -- pragma Assert (Tree.First /= null);
272 -- pragma Assert (Tree.Last /= null);
273 -- pragma Assert (Parent (Tree.Root) = null);
274 -- pragma Assert ((Tree.Length > 1)
275 -- or else (Tree.First = Tree.Last
276 -- and then Tree.First = Tree.Root));
277 -- pragma Assert ((Left (Node) = null)
278 -- or else (Parent (Left (Node)) = Node));
279 -- pragma Assert ((Right (Node) = null)
280 -- or else (Parent (Right (Node)) = Node));
281 -- pragma Assert (((Parent (Node) = null) and then (Tree.Root = Node))
282 -- or else ((Parent (Node) /= null) and then
283 -- ((Left (Parent (Node)) = Node)
284 -- or else (Right (Parent (Node)) = Node))));
286 if Left
(Z
) = null then
287 if Right
(Z
) = null then
288 if Z
= Tree
.First
then
289 Tree
.First
:= Parent
(Z
);
292 if Z
= Tree
.Last
then
293 Tree
.Last
:= Parent
(Z
);
296 if Color
(Z
) = Black
then
297 Delete_Fixup
(Tree
, Z
);
300 pragma Assert
(Left
(Z
) = null);
301 pragma Assert
(Right
(Z
) = null);
303 if Z
= Tree
.Root
then
304 pragma Assert
(Tree
.Length
= 1);
305 pragma Assert
(Parent
(Z
) = null);
307 elsif Z
= Left
(Parent
(Z
)) then
308 Set_Left
(Parent
(Z
), null);
310 pragma Assert
(Z
= Right
(Parent
(Z
)));
311 Set_Right
(Parent
(Z
), null);
315 pragma Assert
(Z
/= Tree
.Last
);
319 if Z
= Tree
.First
then
320 Tree
.First
:= Min
(X
);
323 if Z
= Tree
.Root
then
325 elsif Z
= Left
(Parent
(Z
)) then
326 Set_Left
(Parent
(Z
), X
);
328 pragma Assert
(Z
= Right
(Parent
(Z
)));
329 Set_Right
(Parent
(Z
), X
);
332 Set_Parent
(X
, Parent
(Z
));
334 if Color
(Z
) = Black
then
335 Delete_Fixup
(Tree
, X
);
339 elsif Right
(Z
) = null then
340 pragma Assert
(Z
/= Tree
.First
);
344 if Z
= Tree
.Last
then
345 Tree
.Last
:= Max
(X
);
348 if Z
= Tree
.Root
then
350 elsif Z
= Left
(Parent
(Z
)) then
351 Set_Left
(Parent
(Z
), X
);
353 pragma Assert
(Z
= Right
(Parent
(Z
)));
354 Set_Right
(Parent
(Z
), X
);
357 Set_Parent
(X
, Parent
(Z
));
359 if Color
(Z
) = Black
then
360 Delete_Fixup
(Tree
, X
);
364 pragma Assert
(Z
/= Tree
.First
);
365 pragma Assert
(Z
/= Tree
.Last
);
368 pragma Assert
(Left
(Y
) = null);
373 if Y
= Left
(Parent
(Y
)) then
374 pragma Assert
(Parent
(Y
) /= Z
);
375 Delete_Swap
(Tree
, Z
, Y
);
376 Set_Left
(Parent
(Z
), Z
);
379 pragma Assert
(Y
= Right
(Parent
(Y
)));
380 pragma Assert
(Parent
(Y
) = Z
);
381 Set_Parent
(Y
, Parent
(Z
));
383 if Z
= Tree
.Root
then
385 elsif Z
= Left
(Parent
(Z
)) then
386 Set_Left
(Parent
(Z
), Y
);
388 pragma Assert
(Z
= Right
(Parent
(Z
)));
389 Set_Right
(Parent
(Z
), Y
);
392 Set_Left
(Y
, Left
(Z
));
393 Set_Parent
(Left
(Y
), Y
);
400 Y_Color
: constant Color_Type
:= Color
(Y
);
402 Set_Color
(Y
, Color
(Z
));
403 Set_Color
(Z
, Y_Color
);
407 if Color
(Z
) = Black
then
408 Delete_Fixup
(Tree
, Z
);
411 pragma Assert
(Left
(Z
) = null);
412 pragma Assert
(Right
(Z
) = null);
414 if Z
= Right
(Parent
(Z
)) then
415 Set_Right
(Parent
(Z
), null);
417 pragma Assert
(Z
= Left
(Parent
(Z
)));
418 Set_Left
(Parent
(Z
), null);
422 if Y
= Left
(Parent
(Y
)) then
423 pragma Assert
(Parent
(Y
) /= Z
);
425 Delete_Swap
(Tree
, Z
, Y
);
427 Set_Left
(Parent
(Z
), X
);
428 Set_Parent
(X
, Parent
(Z
));
431 pragma Assert
(Y
= Right
(Parent
(Y
)));
432 pragma Assert
(Parent
(Y
) = Z
);
434 Set_Parent
(Y
, Parent
(Z
));
436 if Z
= Tree
.Root
then
438 elsif Z
= Left
(Parent
(Z
)) then
439 Set_Left
(Parent
(Z
), Y
);
441 pragma Assert
(Z
= Right
(Parent
(Z
)));
442 Set_Right
(Parent
(Z
), Y
);
445 Set_Left
(Y
, Left
(Z
));
446 Set_Parent
(Left
(Y
), Y
);
449 Y_Color
: constant Color_Type
:= Color
(Y
);
451 Set_Color
(Y
, Color
(Z
));
452 Set_Color
(Z
, Y_Color
);
456 if Color
(Z
) = Black
then
457 Delete_Fixup
(Tree
, X
);
462 Tree
.Length
:= Tree
.Length
- 1;
463 end Delete_Node_Sans_Free
;
469 procedure Delete_Swap
470 (Tree
: in out Tree_Type
;
473 pragma Assert
(Z
/= Y
);
474 pragma Assert
(Parent
(Y
) /= Z
);
476 Y_Parent
: constant Node_Access
:= Parent
(Y
);
477 Y_Color
: constant Color_Type
:= Color
(Y
);
480 Set_Parent
(Y
, Parent
(Z
));
481 Set_Left
(Y
, Left
(Z
));
482 Set_Right
(Y
, Right
(Z
));
483 Set_Color
(Y
, Color
(Z
));
485 if Tree
.Root
= Z
then
487 elsif Right
(Parent
(Y
)) = Z
then
488 Set_Right
(Parent
(Y
), Y
);
490 pragma Assert
(Left
(Parent
(Y
)) = Z
);
491 Set_Left
(Parent
(Y
), Y
);
494 if Right
(Y
) /= null then
495 Set_Parent
(Right
(Y
), Y
);
498 if Left
(Y
) /= null then
499 Set_Parent
(Left
(Y
), Y
);
502 Set_Parent
(Z
, Y_Parent
);
503 Set_Color
(Z
, Y_Color
);
512 procedure Generic_Adjust
(Tree
: in out Tree_Type
) is
513 N
: constant Count_Type
:= Tree
.Length
;
514 Root
: constant Node_Access
:= Tree
.Root
;
517 -- If the counts are nonzero, execution is technically erroneous, but
518 -- it seems friendly to allow things like concurrent "=" on shared
521 Zero_Counts
(Tree
.TC
);
524 pragma Assert
(Root
= null);
533 Tree
.Root
:= Copy_Tree
(Root
);
534 Tree
.First
:= Min
(Tree
.Root
);
535 Tree
.Last
:= Max
(Tree
.Root
);
543 procedure Generic_Clear
(Tree
: in out Tree_Type
) is
544 Root
: Node_Access
:= Tree
.Root
;
548 Tree
:= (First
=> null,
557 -----------------------
558 -- Generic_Copy_Tree --
559 -----------------------
561 function Generic_Copy_Tree
(Source_Root
: Node_Access
) return Node_Access
is
562 Target_Root
: Node_Access
:= Copy_Node
(Source_Root
);
566 if Right
(Source_Root
) /= null then
568 (Node
=> Target_Root
,
569 Right
=> Generic_Copy_Tree
(Right
(Source_Root
)));
572 (Node
=> Right
(Target_Root
),
573 Parent
=> Target_Root
);
578 X
:= Left
(Source_Root
);
581 Y
: constant Node_Access
:= Copy_Node
(X
);
583 Set_Left
(Node
=> P
, Left
=> Y
);
584 Set_Parent
(Node
=> Y
, Parent
=> P
);
586 if Right
(X
) /= null then
589 Right
=> Generic_Copy_Tree
(Right
(X
)));
605 Delete_Tree
(Target_Root
);
607 end Generic_Copy_Tree
;
609 -------------------------
610 -- Generic_Delete_Tree --
611 -------------------------
613 procedure Generic_Delete_Tree
(X
: in out Node_Access
) is
615 pragma Warnings
(Off
, Y
);
619 Generic_Delete_Tree
(Y
);
624 end Generic_Delete_Tree
;
630 function Generic_Equal
(Left
, Right
: Tree_Type
) return Boolean is
632 if Left
.Length
/= Right
.Length
then
636 -- If the containers are empty, return a result immediately, so as to
637 -- not manipulate the tamper bits unnecessarily.
639 if Left
.Length
= 0 then
644 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
645 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
647 L_Node
: Node_Access
:= Left
.First
;
648 R_Node
: Node_Access
:= Right
.First
;
650 while L_Node
/= null loop
651 if not Is_Equal
(L_Node
, R_Node
) then
655 L_Node
:= Next
(L_Node
);
656 R_Node
:= Next
(R_Node
);
663 -----------------------
664 -- Generic_Iteration --
665 -----------------------
667 procedure Generic_Iteration
(Tree
: Tree_Type
) is
668 procedure Iterate
(P
: Node_Access
);
674 procedure Iterate
(P
: Node_Access
) is
675 X
: Node_Access
:= P
;
684 -- Start of processing for Generic_Iteration
688 end Generic_Iteration
;
694 procedure Generic_Move
(Target
, Source
: in out Tree_Type
) is
696 if Target
'Address = Source
'Address then
700 TC_Check
(Source
.TC
);
706 Source
:= (First
=> null,
717 procedure Generic_Read
718 (Stream
: not null access Root_Stream_Type
'Class;
719 Tree
: in out Tree_Type
)
723 Node
, Last_Node
: Node_Access
;
728 Count_Type
'Base'Read (Stream, N);
729 pragma Assert (N >= 0);
735 Node := Read_Node (Stream);
736 pragma Assert (Node /= null);
737 pragma Assert (Color (Node) = Red);
739 Set_Color (Node, Black);
747 for J in Count_Type range 2 .. N loop
749 pragma Assert (Last_Node = Tree.Last);
751 Node := Read_Node (Stream);
752 pragma Assert (Node /= null);
753 pragma Assert (Color (Node) = Red);
755 Set_Right (Node => Last_Node, Right => Node);
757 Set_Parent (Node => Node, Parent => Last_Node);
758 Rebalance_For_Insert (Tree, Node);
759 Tree.Length := Tree.Length + 1;
763 -------------------------------
764 -- Generic_Reverse_Iteration --
765 -------------------------------
767 procedure Generic_Reverse_Iteration (Tree : Tree_Type)
769 procedure Iterate (P : Node_Access);
775 procedure Iterate (P : Node_Access) is
776 X : Node_Access := P;
785 -- Start of processing for Generic_Reverse_Iteration
789 end Generic_Reverse_Iteration;
795 procedure Generic_Write
796 (Stream : not null access Root_Stream_Type'Class;
799 procedure Process (Node : Node_Access);
800 pragma Inline (Process);
803 new Generic_Iteration (Process);
809 procedure Process (Node : Node_Access) is
811 Write_Node (Stream, Node);
814 -- Start of processing for Generic_Write
817 Count_Type'Base'Write
(Stream
, Tree
.Length
);
825 procedure Left_Rotate
(Tree
: in out Tree_Type
; X
: Node_Access
) is
829 Y
: constant Node_Access
:= Right
(X
);
830 pragma Assert
(Y
/= null);
833 Set_Right
(X
, Left
(Y
));
835 if Left
(Y
) /= null then
836 Set_Parent
(Left
(Y
), X
);
839 Set_Parent
(Y
, Parent
(X
));
841 if X
= Tree
.Root
then
843 elsif X
= Left
(Parent
(X
)) then
844 Set_Left
(Parent
(X
), Y
);
846 pragma Assert
(X
= Right
(Parent
(X
)));
847 Set_Right
(Parent
(X
), Y
);
858 function Max
(Node
: Node_Access
) return Node_Access
is
862 X
: Node_Access
:= Node
;
881 function Min
(Node
: Node_Access
) return Node_Access
is
885 X
: Node_Access
:= Node
;
904 function Next
(Node
: Node_Access
) return Node_Access
is
912 if Right
(Node
) /= null then
913 return Min
(Right
(Node
));
917 X
: Node_Access
:= Node
;
918 Y
: Node_Access
:= Parent
(Node
);
922 and then X
= Right
(Y
)
936 function Previous
(Node
: Node_Access
) return Node_Access
is
942 if Left
(Node
) /= null then
943 return Max
(Left
(Node
));
947 X
: Node_Access
:= Node
;
948 Y
: Node_Access
:= Parent
(Node
);
952 and then X
= Left
(Y
)
962 --------------------------
963 -- Rebalance_For_Insert --
964 --------------------------
966 procedure Rebalance_For_Insert
967 (Tree
: in out Tree_Type
;
972 X
: Node_Access
:= Node
;
973 pragma Assert
(X
/= null);
974 pragma Assert
(Color
(X
) = Red
);
979 while X
/= Tree
.Root
and then Color
(Parent
(X
)) = Red
loop
980 if Parent
(X
) = Left
(Parent
(Parent
(X
))) then
981 Y
:= Right
(Parent
(Parent
(X
)));
983 if Y
/= null and then Color
(Y
) = Red
then
984 Set_Color
(Parent
(X
), Black
);
985 Set_Color
(Y
, Black
);
986 Set_Color
(Parent
(Parent
(X
)), Red
);
987 X
:= Parent
(Parent
(X
));
990 if X
= Right
(Parent
(X
)) then
992 Left_Rotate
(Tree
, X
);
995 Set_Color
(Parent
(X
), Black
);
996 Set_Color
(Parent
(Parent
(X
)), Red
);
997 Right_Rotate
(Tree
, Parent
(Parent
(X
)));
1001 pragma Assert
(Parent
(X
) = Right
(Parent
(Parent
(X
))));
1003 Y
:= Left
(Parent
(Parent
(X
)));
1005 if Y
/= null and then Color
(Y
) = Red
then
1006 Set_Color
(Parent
(X
), Black
);
1007 Set_Color
(Y
, Black
);
1008 Set_Color
(Parent
(Parent
(X
)), Red
);
1009 X
:= Parent
(Parent
(X
));
1012 if X
= Left
(Parent
(X
)) then
1014 Right_Rotate
(Tree
, X
);
1017 Set_Color
(Parent
(X
), Black
);
1018 Set_Color
(Parent
(Parent
(X
)), Red
);
1019 Left_Rotate
(Tree
, Parent
(Parent
(X
)));
1024 Set_Color
(Tree
.Root
, Black
);
1025 end Rebalance_For_Insert
;
1031 procedure Right_Rotate
(Tree
: in out Tree_Type
; Y
: Node_Access
) is
1032 X
: constant Node_Access
:= Left
(Y
);
1033 pragma Assert
(X
/= null);
1036 Set_Left
(Y
, Right
(X
));
1038 if Right
(X
) /= null then
1039 Set_Parent
(Right
(X
), Y
);
1042 Set_Parent
(X
, Parent
(Y
));
1044 if Y
= Tree
.Root
then
1046 elsif Y
= Left
(Parent
(Y
)) then
1047 Set_Left
(Parent
(Y
), X
);
1049 pragma Assert
(Y
= Right
(Parent
(Y
)));
1050 Set_Right
(Parent
(Y
), X
);
1061 function Vet
(Tree
: Tree_Type
; Node
: Node_Access
) return Boolean is
1067 if Parent
(Node
) = Node
1068 or else Left
(Node
) = Node
1069 or else Right
(Node
) = Node
1075 or else Tree
.Root
= null
1076 or else Tree
.First
= null
1077 or else Tree
.Last
= null
1082 if Parent
(Tree
.Root
) /= null then
1086 if Left
(Tree
.First
) /= null then
1090 if Right
(Tree
.Last
) /= null then
1094 if Tree
.Length
= 1 then
1095 if Tree
.First
/= Tree
.Last
1096 or else Tree
.First
/= Tree
.Root
1101 if Node
/= Tree
.First
then
1105 if Parent
(Node
) /= null
1106 or else Left
(Node
) /= null
1107 or else Right
(Node
) /= null
1115 if Tree
.First
= Tree
.Last
then
1119 if Tree
.Length
= 2 then
1120 if Tree
.First
/= Tree
.Root
1121 and then Tree
.Last
/= Tree
.Root
1126 if Tree
.First
/= Node
1127 and then Tree
.Last
/= Node
1133 if Left
(Node
) /= null
1134 and then Parent
(Left
(Node
)) /= Node
1139 if Right
(Node
) /= null
1140 and then Parent
(Right
(Node
)) /= Node
1145 if Parent
(Node
) = null then
1146 if Tree
.Root
/= Node
then
1150 elsif Left
(Parent
(Node
)) /= Node
1151 and then Right
(Parent
(Node
)) /= Node
1159 end Ada
.Containers
.Red_Black_Trees
.Generic_Operations
;