1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_BOUNDED_OPERATIONS --
9 -- Copyright (C) 2004-2016, 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 in this file to "CLR" refer to the following book, from
31 -- which several of the algorithms here were adapted:
33 -- Introduction to Algorithms
34 -- by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest
35 -- Publisher: The MIT Press (June 18, 1990)
38 with System
; use type System
.Address
;
40 package body Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
is
42 pragma Warnings
(Off
, "variable ""Busy*"" is not referenced");
43 pragma Warnings
(Off
, "variable ""Lock*"" is not referenced");
44 -- See comment in Ada.Containers.Helpers
46 -----------------------
47 -- Local Subprograms --
48 -----------------------
50 procedure Delete_Fixup
(Tree
: in out Tree_Type
'Class; Node
: Count_Type
);
51 procedure Delete_Swap
(Tree
: in out Tree_Type
'Class; Z
, Y
: Count_Type
);
53 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
);
54 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
);
60 procedure Clear_Tree
(Tree
: in out Tree_Type
'Class) is
75 procedure Delete_Fixup
76 (Tree
: in out Tree_Type
'Class;
83 N
: Nodes_Type
renames Tree
.Nodes
;
87 while X
/= Tree
.Root
and then Color
(N
(X
)) = Black
loop
88 if X
= Left
(N
(Parent
(N
(X
)))) then
89 W
:= Right
(N
(Parent
(N
(X
))));
91 if Color
(N
(W
)) = Red
then
92 Set_Color
(N
(W
), Black
);
93 Set_Color
(N
(Parent
(N
(X
))), Red
);
94 Left_Rotate
(Tree
, Parent
(N
(X
)));
95 W
:= Right
(N
(Parent
(N
(X
))));
98 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
100 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
102 Set_Color
(N
(W
), Red
);
107 or else Color
(N
(Right
(N
(W
)))) = Black
109 -- As a condition for setting the color of the left child to
110 -- black, the left child access value must be non-null. A
111 -- truth table analysis shows that if we arrive here, that
112 -- condition holds, so there's no need for an explicit test.
113 -- The assertion is here to document what we know is true.
115 pragma Assert
(Left
(N
(W
)) /= 0);
116 Set_Color
(N
(Left
(N
(W
))), Black
);
118 Set_Color
(N
(W
), Red
);
119 Right_Rotate
(Tree
, W
);
120 W
:= Right
(N
(Parent
(N
(X
))));
123 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
124 Set_Color
(N
(Parent
(N
(X
))), Black
);
125 Set_Color
(N
(Right
(N
(W
))), Black
);
126 Left_Rotate
(Tree
, Parent
(N
(X
)));
131 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
133 W
:= Left
(N
(Parent
(N
(X
))));
135 if Color
(N
(W
)) = Red
then
136 Set_Color
(N
(W
), Black
);
137 Set_Color
(N
(Parent
(N
(X
))), Red
);
138 Right_Rotate
(Tree
, Parent
(N
(X
)));
139 W
:= Left
(N
(Parent
(N
(X
))));
142 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
144 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
146 Set_Color
(N
(W
), Red
);
151 or else Color
(N
(Left
(N
(W
)))) = Black
153 -- As a condition for setting the color of the right child
154 -- to black, the right child access value must be non-null.
155 -- A truth table analysis shows that if we arrive here, that
156 -- condition holds, so there's no need for an explicit test.
157 -- The assertion is here to document what we know is true.
159 pragma Assert
(Right
(N
(W
)) /= 0);
160 Set_Color
(N
(Right
(N
(W
))), Black
);
162 Set_Color
(N
(W
), Red
);
163 Left_Rotate
(Tree
, W
);
164 W
:= Left
(N
(Parent
(N
(X
))));
167 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
168 Set_Color
(N
(Parent
(N
(X
))), Black
);
169 Set_Color
(N
(Left
(N
(W
))), Black
);
170 Right_Rotate
(Tree
, Parent
(N
(X
)));
176 Set_Color
(N
(X
), Black
);
179 ---------------------------
180 -- Delete_Node_Sans_Free --
181 ---------------------------
183 procedure Delete_Node_Sans_Free
184 (Tree
: in out Tree_Type
'Class;
191 Z
: constant Count_Type
:= Node
;
193 N
: Nodes_Type
renames Tree
.Nodes
;
198 -- If node is not present, return (exception will be raised in caller)
204 pragma Assert
(Tree
.Length
> 0);
205 pragma Assert
(Tree
.Root
/= 0);
206 pragma Assert
(Tree
.First
/= 0);
207 pragma Assert
(Tree
.Last
/= 0);
208 pragma Assert
(Parent
(N
(Tree
.Root
)) = 0);
210 pragma Assert
((Tree
.Length
> 1)
211 or else (Tree
.First
= Tree
.Last
212 and then Tree
.First
= Tree
.Root
));
214 pragma Assert
((Left
(N
(Node
)) = 0)
215 or else (Parent
(N
(Left
(N
(Node
)))) = Node
));
217 pragma Assert
((Right
(N
(Node
)) = 0)
218 or else (Parent
(N
(Right
(N
(Node
)))) = Node
));
220 pragma Assert
(((Parent
(N
(Node
)) = 0) and then (Tree
.Root
= Node
))
221 or else ((Parent
(N
(Node
)) /= 0) and then
222 ((Left
(N
(Parent
(N
(Node
)))) = Node
)
224 (Right
(N
(Parent
(N
(Node
)))) = Node
))));
226 if Left
(N
(Z
)) = 0 then
227 if Right
(N
(Z
)) = 0 then
228 if Z
= Tree
.First
then
229 Tree
.First
:= Parent
(N
(Z
));
232 if Z
= Tree
.Last
then
233 Tree
.Last
:= Parent
(N
(Z
));
236 if Color
(N
(Z
)) = Black
then
237 Delete_Fixup
(Tree
, Z
);
240 pragma Assert
(Left
(N
(Z
)) = 0);
241 pragma Assert
(Right
(N
(Z
)) = 0);
243 if Z
= Tree
.Root
then
244 pragma Assert
(Tree
.Length
= 1);
245 pragma Assert
(Parent
(N
(Z
)) = 0);
247 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
248 Set_Left
(N
(Parent
(N
(Z
))), 0);
250 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
251 Set_Right
(N
(Parent
(N
(Z
))), 0);
255 pragma Assert
(Z
/= Tree
.Last
);
259 if Z
= Tree
.First
then
260 Tree
.First
:= Min
(Tree
, X
);
263 if Z
= Tree
.Root
then
265 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
266 Set_Left
(N
(Parent
(N
(Z
))), X
);
268 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
269 Set_Right
(N
(Parent
(N
(Z
))), X
);
272 Set_Parent
(N
(X
), Parent
(N
(Z
)));
274 if Color
(N
(Z
)) = Black
then
275 Delete_Fixup
(Tree
, X
);
279 elsif Right
(N
(Z
)) = 0 then
280 pragma Assert
(Z
/= Tree
.First
);
284 if Z
= Tree
.Last
then
285 Tree
.Last
:= Max
(Tree
, X
);
288 if Z
= Tree
.Root
then
290 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
291 Set_Left
(N
(Parent
(N
(Z
))), X
);
293 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
294 Set_Right
(N
(Parent
(N
(Z
))), X
);
297 Set_Parent
(N
(X
), Parent
(N
(Z
)));
299 if Color
(N
(Z
)) = Black
then
300 Delete_Fixup
(Tree
, X
);
304 pragma Assert
(Z
/= Tree
.First
);
305 pragma Assert
(Z
/= Tree
.Last
);
308 pragma Assert
(Left
(N
(Y
)) = 0);
313 if Y
= Left
(N
(Parent
(N
(Y
)))) then
314 pragma Assert
(Parent
(N
(Y
)) /= Z
);
315 Delete_Swap
(Tree
, Z
, Y
);
316 Set_Left
(N
(Parent
(N
(Z
))), Z
);
319 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
320 pragma Assert
(Parent
(N
(Y
)) = Z
);
321 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
323 if Z
= Tree
.Root
then
325 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
326 Set_Left
(N
(Parent
(N
(Z
))), Y
);
328 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
329 Set_Right
(N
(Parent
(N
(Z
))), Y
);
332 Set_Left
(N
(Y
), Left
(N
(Z
)));
333 Set_Parent
(N
(Left
(N
(Y
))), Y
);
334 Set_Right
(N
(Y
), Z
);
336 Set_Parent
(N
(Z
), Y
);
338 Set_Right
(N
(Z
), 0);
341 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
343 Set_Color
(N
(Y
), Color
(N
(Z
)));
344 Set_Color
(N
(Z
), Y_Color
);
348 if Color
(N
(Z
)) = Black
then
349 Delete_Fixup
(Tree
, Z
);
352 pragma Assert
(Left
(N
(Z
)) = 0);
353 pragma Assert
(Right
(N
(Z
)) = 0);
355 if Z
= Right
(N
(Parent
(N
(Z
)))) then
356 Set_Right
(N
(Parent
(N
(Z
))), 0);
358 pragma Assert
(Z
= Left
(N
(Parent
(N
(Z
)))));
359 Set_Left
(N
(Parent
(N
(Z
))), 0);
363 if Y
= Left
(N
(Parent
(N
(Y
)))) then
364 pragma Assert
(Parent
(N
(Y
)) /= Z
);
366 Delete_Swap
(Tree
, Z
, Y
);
368 Set_Left
(N
(Parent
(N
(Z
))), X
);
369 Set_Parent
(N
(X
), Parent
(N
(Z
)));
372 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
373 pragma Assert
(Parent
(N
(Y
)) = Z
);
375 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
377 if Z
= Tree
.Root
then
379 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
380 Set_Left
(N
(Parent
(N
(Z
))), Y
);
382 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
383 Set_Right
(N
(Parent
(N
(Z
))), Y
);
386 Set_Left
(N
(Y
), Left
(N
(Z
)));
387 Set_Parent
(N
(Left
(N
(Y
))), Y
);
390 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
392 Set_Color
(N
(Y
), Color
(N
(Z
)));
393 Set_Color
(N
(Z
), Y_Color
);
397 if Color
(N
(Z
)) = Black
then
398 Delete_Fixup
(Tree
, X
);
403 Tree
.Length
:= Tree
.Length
- 1;
404 end Delete_Node_Sans_Free
;
410 procedure Delete_Swap
411 (Tree
: in out Tree_Type
'Class;
414 N
: Nodes_Type
renames Tree
.Nodes
;
416 pragma Assert
(Z
/= Y
);
417 pragma Assert
(Parent
(N
(Y
)) /= Z
);
419 Y_Parent
: constant Count_Type
:= Parent
(N
(Y
));
420 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
423 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
424 Set_Left
(N
(Y
), Left
(N
(Z
)));
425 Set_Right
(N
(Y
), Right
(N
(Z
)));
426 Set_Color
(N
(Y
), Color
(N
(Z
)));
428 if Tree
.Root
= Z
then
430 elsif Right
(N
(Parent
(N
(Y
)))) = Z
then
431 Set_Right
(N
(Parent
(N
(Y
))), Y
);
433 pragma Assert
(Left
(N
(Parent
(N
(Y
)))) = Z
);
434 Set_Left
(N
(Parent
(N
(Y
))), Y
);
437 if Right
(N
(Y
)) /= 0 then
438 Set_Parent
(N
(Right
(N
(Y
))), Y
);
441 if Left
(N
(Y
)) /= 0 then
442 Set_Parent
(N
(Left
(N
(Y
))), Y
);
445 Set_Parent
(N
(Z
), Y_Parent
);
446 Set_Color
(N
(Z
), Y_Color
);
448 Set_Right
(N
(Z
), 0);
455 procedure Free
(Tree
: in out Tree_Type
'Class; X
: Count_Type
) is
456 pragma Assert
(X
> 0);
457 pragma Assert
(X
<= Tree
.Capacity
);
459 N
: Nodes_Type
renames Tree
.Nodes
;
460 -- pragma Assert (N (X).Prev >= 0); -- node is active
461 -- Find a way to mark a node as active vs. inactive; we could
462 -- use a special value in Color_Type for this. ???
465 -- The set container actually contains two data structures: a list for
466 -- the "active" nodes that contain elements that have been inserted
467 -- onto the tree, and another for the "inactive" nodes of the free
470 -- We desire that merely declaring an object should have only minimal
471 -- cost; specially, we want to avoid having to initialize the free
472 -- store (to fill in the links), especially if the capacity is large.
474 -- The head of the free list is indicated by Container.Free. If its
475 -- value is non-negative, then the free store has been initialized
476 -- in the "normal" way: Container.Free points to the head of the list
477 -- of free (inactive) nodes, and the value 0 means the free list is
478 -- empty. Each node on the free list has been initialized to point
479 -- to the next free node (via its Parent component), and the value 0
480 -- means that this is the last free node.
482 -- If Container.Free is negative, then the links on the free store
483 -- have not been initialized. In this case the link values are
484 -- implied: the free store comprises the components of the node array
485 -- started with the absolute value of Container.Free, and continuing
486 -- until the end of the array (Nodes'Last).
489 -- It might be possible to perform an optimization here. Suppose that
490 -- the free store can be represented as having two parts: one
491 -- comprising the non-contiguous inactive nodes linked together
492 -- in the normal way, and the other comprising the contiguous
493 -- inactive nodes (that are not linked together, at the end of the
494 -- nodes array). This would allow us to never have to initialize
495 -- the free store, except in a lazy way as nodes become inactive.
497 -- When an element is deleted from the list container, its node
498 -- becomes inactive, and so we set its Prev component to a negative
499 -- value, to indicate that it is now inactive. This provides a useful
500 -- way to detect a dangling cursor reference.
502 -- The comment above is incorrect; we need some other way to
503 -- indicate a node is inactive, for example by using a special
504 -- Color_Type value. ???
505 -- N (X).Prev := -1; -- Node is deallocated (not on active list)
507 if Tree
.Free
>= 0 then
508 -- The free store has previously been initialized. All we need to
509 -- do here is link the newly-free'd node onto the free list.
511 Set_Parent
(N
(X
), Tree
.Free
);
514 elsif X
+ 1 = abs Tree
.Free
then
515 -- The free store has not been initialized, and the node becoming
516 -- inactive immediately precedes the start of the free store. All
517 -- we need to do is move the start of the free store back by one.
519 Tree
.Free
:= Tree
.Free
+ 1;
522 -- The free store has not been initialized, and the node becoming
523 -- inactive does not immediately precede the free store. Here we
524 -- first initialize the free store (meaning the links are given
525 -- values in the traditional way), and then link the newly-free'd
526 -- node onto the head of the free store.
529 -- See the comments above for an optimization opportunity. If the
530 -- next link for a node on the free store is negative, then this
531 -- means the remaining nodes on the free store are physically
532 -- contiguous, starting as the absolute value of that index value.
534 Tree
.Free
:= abs Tree
.Free
;
536 if Tree
.Free
> Tree
.Capacity
then
540 for I
in Tree
.Free
.. Tree
.Capacity
- 1 loop
541 Set_Parent
(N
(I
), I
+ 1);
544 Set_Parent
(N
(Tree
.Capacity
), 0);
547 Set_Parent
(N
(X
), Tree
.Free
);
552 -----------------------
553 -- Generic_Allocate --
554 -----------------------
556 procedure Generic_Allocate
557 (Tree
: in out Tree_Type
'Class;
558 Node
: out Count_Type
)
560 N
: Nodes_Type
renames Tree
.Nodes
;
563 if Tree
.Free
>= 0 then
566 -- We always perform the assignment first, before we
567 -- change container state, in order to defend against
568 -- exceptions duration assignment.
570 Set_Element
(N
(Node
));
571 Tree
.Free
:= Parent
(N
(Node
));
574 -- A negative free store value means that the links of the nodes
575 -- in the free store have not been initialized. In this case, the
576 -- nodes are physically contiguous in the array, starting at the
577 -- index that is the absolute value of the Container.Free, and
578 -- continuing until the end of the array (Nodes'Last).
580 Node
:= abs Tree
.Free
;
582 -- As above, we perform this assignment first, before modifying
583 -- any container state.
585 Set_Element
(N
(Node
));
586 Tree
.Free
:= Tree
.Free
- 1;
589 -- When a node is allocated from the free store, its pointer components
590 -- (the links to other nodes in the tree) must also be initialized (to
591 -- 0, the equivalent of null). This simplifies the post-allocation
592 -- handling of nodes inserted into terminal positions.
594 Set_Parent
(N
(Node
), Parent
=> 0);
595 Set_Left
(N
(Node
), Left
=> 0);
596 Set_Right
(N
(Node
), Right
=> 0);
597 end Generic_Allocate
;
603 function Generic_Equal
(Left
, Right
: Tree_Type
'Class) return Boolean is
604 -- Per AI05-0022, the container implementation is required to detect
605 -- element tampering by a generic actual subprogram.
607 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
608 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
614 if Left
'Address = Right
'Address then
618 if Left
.Length
/= Right
.Length
then
622 -- If the containers are empty, return a result immediately, so as to
623 -- not manipulate the tamper bits unnecessarily.
625 if Left
.Length
= 0 then
629 L_Node
:= Left
.First
;
630 R_Node
:= Right
.First
;
631 while L_Node
/= 0 loop
632 if not Is_Equal
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
636 L_Node
:= Next
(Left
, L_Node
);
637 R_Node
:= Next
(Right
, R_Node
);
643 -----------------------
644 -- Generic_Iteration --
645 -----------------------
647 procedure Generic_Iteration
(Tree
: Tree_Type
'Class) is
648 procedure Iterate
(P
: Count_Type
);
654 procedure Iterate
(P
: Count_Type
) is
658 Iterate
(Left
(Tree
.Nodes
(X
)));
660 X
:= Right
(Tree
.Nodes
(X
));
664 -- Start of processing for Generic_Iteration
668 end Generic_Iteration
;
674 procedure Generic_Read
675 (Stream
: not null access Root_Stream_Type
'Class;
676 Tree
: in out Tree_Type
'Class)
678 Len
: Count_Type
'Base;
680 Node
, Last_Node
: Count_Type
;
682 N
: Nodes_Type
renames Tree
.Nodes
;
686 Count_Type
'Base'Read (Stream, Len);
688 if Checks and then Len < 0 then
689 raise Program_Error with "bad container length (corrupt stream)";
696 if Checks and then Len > Tree.Capacity then
697 raise Constraint_Error with "length exceeds capacity";
700 -- Use Unconditional_Insert_With_Hint here instead ???
702 Allocate (Tree, Node);
703 pragma Assert (Node /= 0);
705 Set_Color (N (Node), Black);
712 for J in Count_Type range 2 .. Len loop
714 pragma Assert (Last_Node = Tree.Last);
716 Allocate (Tree, Node);
717 pragma Assert (Node /= 0);
719 Set_Color (N (Node), Red);
720 Set_Right (N (Last_Node), Right => Node);
722 Set_Parent (N (Node), Parent => Last_Node);
724 Rebalance_For_Insert (Tree, Node);
725 Tree.Length := Tree.Length + 1;
729 -------------------------------
730 -- Generic_Reverse_Iteration --
731 -------------------------------
733 procedure Generic_Reverse_Iteration (Tree : Tree_Type'Class) is
734 procedure Iterate (P : Count_Type);
740 procedure Iterate (P : Count_Type) is
744 Iterate (Right (Tree.Nodes (X)));
746 X := Left (Tree.Nodes (X));
750 -- Start of processing for Generic_Reverse_Iteration
754 end Generic_Reverse_Iteration;
760 procedure Generic_Write
761 (Stream : not null access Root_Stream_Type'Class;
762 Tree : Tree_Type'Class)
764 procedure Process (Node : Count_Type);
765 pragma Inline (Process);
767 procedure Iterate is new Generic_Iteration (Process);
773 procedure Process (Node : Count_Type) is
775 Write_Node (Stream, Tree.Nodes (Node));
778 -- Start of processing for Generic_Write
781 Count_Type'Base'Write
(Stream
, Tree
.Length
);
789 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
) is
793 N
: Nodes_Type
renames Tree
.Nodes
;
795 Y
: constant Count_Type
:= Right
(N
(X
));
796 pragma Assert
(Y
/= 0);
799 Set_Right
(N
(X
), Left
(N
(Y
)));
801 if Left
(N
(Y
)) /= 0 then
802 Set_Parent
(N
(Left
(N
(Y
))), X
);
805 Set_Parent
(N
(Y
), Parent
(N
(X
)));
807 if X
= Tree
.Root
then
809 elsif X
= Left
(N
(Parent
(N
(X
)))) then
810 Set_Left
(N
(Parent
(N
(X
))), Y
);
812 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
813 Set_Right
(N
(Parent
(N
(X
))), Y
);
817 Set_Parent
(N
(X
), Y
);
825 (Tree
: Tree_Type
'Class;
826 Node
: Count_Type
) return Count_Type
830 X
: Count_Type
:= Node
;
835 Y
:= Right
(Tree
.Nodes
(X
));
850 (Tree
: Tree_Type
'Class;
851 Node
: Count_Type
) return Count_Type
855 X
: Count_Type
:= Node
;
860 Y
:= Left
(Tree
.Nodes
(X
));
875 (Tree
: Tree_Type
'Class;
876 Node
: Count_Type
) return Count_Type
885 if Right
(Tree
.Nodes
(Node
)) /= 0 then
886 return Min
(Tree
, Right
(Tree
.Nodes
(Node
)));
890 X
: Count_Type
:= Node
;
891 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
894 while Y
/= 0 and then X
= Right
(Tree
.Nodes
(Y
)) loop
896 Y
:= Parent
(Tree
.Nodes
(Y
));
908 (Tree
: Tree_Type
'Class;
909 Node
: Count_Type
) return Count_Type
916 if Left
(Tree
.Nodes
(Node
)) /= 0 then
917 return Max
(Tree
, Left
(Tree
.Nodes
(Node
)));
921 X
: Count_Type
:= Node
;
922 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
925 while Y
/= 0 and then X
= Left
(Tree
.Nodes
(Y
)) loop
927 Y
:= Parent
(Tree
.Nodes
(Y
));
934 --------------------------
935 -- Rebalance_For_Insert --
936 --------------------------
938 procedure Rebalance_For_Insert
939 (Tree
: in out Tree_Type
'Class;
944 N
: Nodes_Type
renames Tree
.Nodes
;
946 X
: Count_Type
:= Node
;
947 pragma Assert
(X
/= 0);
948 pragma Assert
(Color
(N
(X
)) = Red
);
953 while X
/= Tree
.Root
and then Color
(N
(Parent
(N
(X
)))) = Red
loop
954 if Parent
(N
(X
)) = Left
(N
(Parent
(N
(Parent
(N
(X
)))))) then
955 Y
:= Right
(N
(Parent
(N
(Parent
(N
(X
))))));
957 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
958 Set_Color
(N
(Parent
(N
(X
))), Black
);
959 Set_Color
(N
(Y
), Black
);
960 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
961 X
:= Parent
(N
(Parent
(N
(X
))));
964 if X
= Right
(N
(Parent
(N
(X
)))) then
966 Left_Rotate
(Tree
, X
);
969 Set_Color
(N
(Parent
(N
(X
))), Black
);
970 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
971 Right_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
975 pragma Assert
(Parent
(N
(X
)) =
976 Right
(N
(Parent
(N
(Parent
(N
(X
)))))));
978 Y
:= Left
(N
(Parent
(N
(Parent
(N
(X
))))));
980 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
981 Set_Color
(N
(Parent
(N
(X
))), Black
);
982 Set_Color
(N
(Y
), Black
);
983 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
984 X
:= Parent
(N
(Parent
(N
(X
))));
987 if X
= Left
(N
(Parent
(N
(X
)))) then
989 Right_Rotate
(Tree
, X
);
992 Set_Color
(N
(Parent
(N
(X
))), Black
);
993 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
994 Left_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
999 Set_Color
(N
(Tree
.Root
), Black
);
1000 end Rebalance_For_Insert
;
1006 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
) is
1007 N
: Nodes_Type
renames Tree
.Nodes
;
1009 X
: constant Count_Type
:= Left
(N
(Y
));
1010 pragma Assert
(X
/= 0);
1013 Set_Left
(N
(Y
), Right
(N
(X
)));
1015 if Right
(N
(X
)) /= 0 then
1016 Set_Parent
(N
(Right
(N
(X
))), Y
);
1019 Set_Parent
(N
(X
), Parent
(N
(Y
)));
1021 if Y
= Tree
.Root
then
1023 elsif Y
= Left
(N
(Parent
(N
(Y
)))) then
1024 Set_Left
(N
(Parent
(N
(Y
))), X
);
1026 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
1027 Set_Right
(N
(Parent
(N
(Y
))), X
);
1030 Set_Right
(N
(X
), Y
);
1031 Set_Parent
(N
(Y
), X
);
1038 function Vet
(Tree
: Tree_Type
'Class; Index
: Count_Type
) return Boolean is
1039 Nodes
: Nodes_Type
renames Tree
.Nodes
;
1040 Node
: Node_Type
renames Nodes
(Index
);
1043 if Parent
(Node
) = Index
1044 or else Left
(Node
) = Index
1045 or else Right
(Node
) = Index
1051 or else Tree
.Root
= 0
1052 or else Tree
.First
= 0
1053 or else Tree
.Last
= 0
1058 if Parent
(Nodes
(Tree
.Root
)) /= 0 then
1062 if Left
(Nodes
(Tree
.First
)) /= 0 then
1066 if Right
(Nodes
(Tree
.Last
)) /= 0 then
1070 if Tree
.Length
= 1 then
1071 if Tree
.First
/= Tree
.Last
1072 or else Tree
.First
/= Tree
.Root
1077 if Index
/= Tree
.First
then
1081 if Parent
(Node
) /= 0
1082 or else Left
(Node
) /= 0
1083 or else Right
(Node
) /= 0
1091 if Tree
.First
= Tree
.Last
then
1095 if Tree
.Length
= 2 then
1096 if Tree
.First
/= Tree
.Root
and then Tree
.Last
/= Tree
.Root
then
1100 if Tree
.First
/= Index
and then Tree
.Last
/= Index
then
1105 if Left
(Node
) /= 0 and then Parent
(Nodes
(Left
(Node
))) /= Index
then
1109 if Right
(Node
) /= 0 and then Parent
(Nodes
(Right
(Node
))) /= Index
then
1113 if Parent
(Node
) = 0 then
1114 if Tree
.Root
/= Index
then
1118 elsif Left
(Nodes
(Parent
(Node
))) /= Index
1119 and then Right
(Nodes
(Parent
(Node
))) /= Index
1127 end Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
;