1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_BOUNDED_OPERATIONS --
9 -- Copyright (C) 2004-2014, 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 Annotate
(CodePeer
, Skip_Analysis
);
44 -----------------------
45 -- Local Subprograms --
46 -----------------------
48 procedure Delete_Fixup
(Tree
: in out Tree_Type
'Class; Node
: Count_Type
);
49 procedure Delete_Swap
(Tree
: in out Tree_Type
'Class; Z
, Y
: Count_Type
);
51 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
);
52 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
);
58 procedure Clear_Tree
(Tree
: in out Tree_Type
'Class) is
61 raise Program_Error
with
62 "attempt to tamper with cursors (container is busy)";
65 -- The lock status (which monitors "element tampering") always implies
66 -- that the busy status (which monitors "cursor tampering") is set too;
67 -- this is a representation invariant. Thus if the busy bit is not set,
68 -- then the lock bit must not be set either.
70 pragma Assert
(Tree
.Lock
= 0);
83 procedure Delete_Fixup
84 (Tree
: in out Tree_Type
'Class;
91 N
: Nodes_Type
renames Tree
.Nodes
;
95 while X
/= Tree
.Root
and then Color
(N
(X
)) = Black
loop
96 if X
= Left
(N
(Parent
(N
(X
)))) then
97 W
:= Right
(N
(Parent
(N
(X
))));
99 if Color
(N
(W
)) = Red
then
100 Set_Color
(N
(W
), Black
);
101 Set_Color
(N
(Parent
(N
(X
))), Red
);
102 Left_Rotate
(Tree
, Parent
(N
(X
)));
103 W
:= Right
(N
(Parent
(N
(X
))));
106 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
108 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
110 Set_Color
(N
(W
), Red
);
115 or else Color
(N
(Right
(N
(W
)))) = Black
117 -- As a condition for setting the color of the left child to
118 -- black, the left child access value must be non-null. A
119 -- truth table analysis shows that if we arrive here, that
120 -- condition holds, so there's no need for an explicit test.
121 -- The assertion is here to document what we know is true.
123 pragma Assert
(Left
(N
(W
)) /= 0);
124 Set_Color
(N
(Left
(N
(W
))), Black
);
126 Set_Color
(N
(W
), Red
);
127 Right_Rotate
(Tree
, W
);
128 W
:= Right
(N
(Parent
(N
(X
))));
131 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
132 Set_Color
(N
(Parent
(N
(X
))), Black
);
133 Set_Color
(N
(Right
(N
(W
))), Black
);
134 Left_Rotate
(Tree
, Parent
(N
(X
)));
139 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
141 W
:= Left
(N
(Parent
(N
(X
))));
143 if Color
(N
(W
)) = Red
then
144 Set_Color
(N
(W
), Black
);
145 Set_Color
(N
(Parent
(N
(X
))), Red
);
146 Right_Rotate
(Tree
, Parent
(N
(X
)));
147 W
:= Left
(N
(Parent
(N
(X
))));
150 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
152 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
154 Set_Color
(N
(W
), Red
);
159 or else Color
(N
(Left
(N
(W
)))) = Black
161 -- As a condition for setting the color of the right child
162 -- to black, the right child access value must be non-null.
163 -- A truth table analysis shows that if we arrive here, that
164 -- condition holds, so there's no need for an explicit test.
165 -- The assertion is here to document what we know is true.
167 pragma Assert
(Right
(N
(W
)) /= 0);
168 Set_Color
(N
(Right
(N
(W
))), Black
);
170 Set_Color
(N
(W
), Red
);
171 Left_Rotate
(Tree
, W
);
172 W
:= Left
(N
(Parent
(N
(X
))));
175 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
176 Set_Color
(N
(Parent
(N
(X
))), Black
);
177 Set_Color
(N
(Left
(N
(W
))), Black
);
178 Right_Rotate
(Tree
, Parent
(N
(X
)));
184 Set_Color
(N
(X
), Black
);
187 ---------------------------
188 -- Delete_Node_Sans_Free --
189 ---------------------------
191 procedure Delete_Node_Sans_Free
192 (Tree
: in out Tree_Type
'Class;
199 Z
: constant Count_Type
:= Node
;
201 N
: Nodes_Type
renames Tree
.Nodes
;
204 if Tree
.Busy
> 0 then
205 raise Program_Error
with
206 "attempt to tamper with cursors (container is busy)";
209 -- If node is not present, return (exception will be raised in caller)
215 pragma Assert
(Tree
.Length
> 0);
216 pragma Assert
(Tree
.Root
/= 0);
217 pragma Assert
(Tree
.First
/= 0);
218 pragma Assert
(Tree
.Last
/= 0);
219 pragma Assert
(Parent
(N
(Tree
.Root
)) = 0);
221 pragma Assert
((Tree
.Length
> 1)
222 or else (Tree
.First
= Tree
.Last
223 and then Tree
.First
= Tree
.Root
));
225 pragma Assert
((Left
(N
(Node
)) = 0)
226 or else (Parent
(N
(Left
(N
(Node
)))) = Node
));
228 pragma Assert
((Right
(N
(Node
)) = 0)
229 or else (Parent
(N
(Right
(N
(Node
)))) = Node
));
231 pragma Assert
(((Parent
(N
(Node
)) = 0) and then (Tree
.Root
= Node
))
232 or else ((Parent
(N
(Node
)) /= 0) and then
233 ((Left
(N
(Parent
(N
(Node
)))) = Node
)
235 (Right
(N
(Parent
(N
(Node
)))) = Node
))));
237 if Left
(N
(Z
)) = 0 then
238 if Right
(N
(Z
)) = 0 then
239 if Z
= Tree
.First
then
240 Tree
.First
:= Parent
(N
(Z
));
243 if Z
= Tree
.Last
then
244 Tree
.Last
:= Parent
(N
(Z
));
247 if Color
(N
(Z
)) = Black
then
248 Delete_Fixup
(Tree
, Z
);
251 pragma Assert
(Left
(N
(Z
)) = 0);
252 pragma Assert
(Right
(N
(Z
)) = 0);
254 if Z
= Tree
.Root
then
255 pragma Assert
(Tree
.Length
= 1);
256 pragma Assert
(Parent
(N
(Z
)) = 0);
258 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
259 Set_Left
(N
(Parent
(N
(Z
))), 0);
261 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
262 Set_Right
(N
(Parent
(N
(Z
))), 0);
266 pragma Assert
(Z
/= Tree
.Last
);
270 if Z
= Tree
.First
then
271 Tree
.First
:= Min
(Tree
, X
);
274 if Z
= Tree
.Root
then
276 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
277 Set_Left
(N
(Parent
(N
(Z
))), X
);
279 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
280 Set_Right
(N
(Parent
(N
(Z
))), X
);
283 Set_Parent
(N
(X
), Parent
(N
(Z
)));
285 if Color
(N
(Z
)) = Black
then
286 Delete_Fixup
(Tree
, X
);
290 elsif Right
(N
(Z
)) = 0 then
291 pragma Assert
(Z
/= Tree
.First
);
295 if Z
= Tree
.Last
then
296 Tree
.Last
:= Max
(Tree
, X
);
299 if Z
= Tree
.Root
then
301 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
302 Set_Left
(N
(Parent
(N
(Z
))), X
);
304 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
305 Set_Right
(N
(Parent
(N
(Z
))), X
);
308 Set_Parent
(N
(X
), Parent
(N
(Z
)));
310 if Color
(N
(Z
)) = Black
then
311 Delete_Fixup
(Tree
, X
);
315 pragma Assert
(Z
/= Tree
.First
);
316 pragma Assert
(Z
/= Tree
.Last
);
319 pragma Assert
(Left
(N
(Y
)) = 0);
324 if Y
= Left
(N
(Parent
(N
(Y
)))) then
325 pragma Assert
(Parent
(N
(Y
)) /= Z
);
326 Delete_Swap
(Tree
, Z
, Y
);
327 Set_Left
(N
(Parent
(N
(Z
))), Z
);
330 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
331 pragma Assert
(Parent
(N
(Y
)) = Z
);
332 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
334 if Z
= Tree
.Root
then
336 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
337 Set_Left
(N
(Parent
(N
(Z
))), Y
);
339 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
340 Set_Right
(N
(Parent
(N
(Z
))), Y
);
343 Set_Left
(N
(Y
), Left
(N
(Z
)));
344 Set_Parent
(N
(Left
(N
(Y
))), Y
);
345 Set_Right
(N
(Y
), Z
);
347 Set_Parent
(N
(Z
), Y
);
349 Set_Right
(N
(Z
), 0);
352 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
354 Set_Color
(N
(Y
), Color
(N
(Z
)));
355 Set_Color
(N
(Z
), Y_Color
);
359 if Color
(N
(Z
)) = Black
then
360 Delete_Fixup
(Tree
, Z
);
363 pragma Assert
(Left
(N
(Z
)) = 0);
364 pragma Assert
(Right
(N
(Z
)) = 0);
366 if Z
= Right
(N
(Parent
(N
(Z
)))) then
367 Set_Right
(N
(Parent
(N
(Z
))), 0);
369 pragma Assert
(Z
= Left
(N
(Parent
(N
(Z
)))));
370 Set_Left
(N
(Parent
(N
(Z
))), 0);
374 if Y
= Left
(N
(Parent
(N
(Y
)))) then
375 pragma Assert
(Parent
(N
(Y
)) /= Z
);
377 Delete_Swap
(Tree
, Z
, Y
);
379 Set_Left
(N
(Parent
(N
(Z
))), X
);
380 Set_Parent
(N
(X
), Parent
(N
(Z
)));
383 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
384 pragma Assert
(Parent
(N
(Y
)) = Z
);
386 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
388 if Z
= Tree
.Root
then
390 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
391 Set_Left
(N
(Parent
(N
(Z
))), Y
);
393 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
394 Set_Right
(N
(Parent
(N
(Z
))), Y
);
397 Set_Left
(N
(Y
), Left
(N
(Z
)));
398 Set_Parent
(N
(Left
(N
(Y
))), Y
);
401 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
403 Set_Color
(N
(Y
), Color
(N
(Z
)));
404 Set_Color
(N
(Z
), Y_Color
);
408 if Color
(N
(Z
)) = Black
then
409 Delete_Fixup
(Tree
, X
);
414 Tree
.Length
:= Tree
.Length
- 1;
415 end Delete_Node_Sans_Free
;
421 procedure Delete_Swap
422 (Tree
: in out Tree_Type
'Class;
425 N
: Nodes_Type
renames Tree
.Nodes
;
427 pragma Assert
(Z
/= Y
);
428 pragma Assert
(Parent
(N
(Y
)) /= Z
);
430 Y_Parent
: constant Count_Type
:= Parent
(N
(Y
));
431 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
434 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
435 Set_Left
(N
(Y
), Left
(N
(Z
)));
436 Set_Right
(N
(Y
), Right
(N
(Z
)));
437 Set_Color
(N
(Y
), Color
(N
(Z
)));
439 if Tree
.Root
= Z
then
441 elsif Right
(N
(Parent
(N
(Y
)))) = Z
then
442 Set_Right
(N
(Parent
(N
(Y
))), Y
);
444 pragma Assert
(Left
(N
(Parent
(N
(Y
)))) = Z
);
445 Set_Left
(N
(Parent
(N
(Y
))), Y
);
448 if Right
(N
(Y
)) /= 0 then
449 Set_Parent
(N
(Right
(N
(Y
))), Y
);
452 if Left
(N
(Y
)) /= 0 then
453 Set_Parent
(N
(Left
(N
(Y
))), Y
);
456 Set_Parent
(N
(Z
), Y_Parent
);
457 Set_Color
(N
(Z
), Y_Color
);
459 Set_Right
(N
(Z
), 0);
466 procedure Free
(Tree
: in out Tree_Type
'Class; X
: Count_Type
) is
467 pragma Assert
(X
> 0);
468 pragma Assert
(X
<= Tree
.Capacity
);
470 N
: Nodes_Type
renames Tree
.Nodes
;
471 -- pragma Assert (N (X).Prev >= 0); -- node is active
472 -- Find a way to mark a node as active vs. inactive; we could
473 -- use a special value in Color_Type for this. ???
476 -- The set container actually contains two data structures: a list for
477 -- the "active" nodes that contain elements that have been inserted
478 -- onto the tree, and another for the "inactive" nodes of the free
481 -- We desire that merely declaring an object should have only minimal
482 -- cost; specially, we want to avoid having to initialize the free
483 -- store (to fill in the links), especially if the capacity is large.
485 -- The head of the free list is indicated by Container.Free. If its
486 -- value is non-negative, then the free store has been initialized
487 -- in the "normal" way: Container.Free points to the head of the list
488 -- of free (inactive) nodes, and the value 0 means the free list is
489 -- empty. Each node on the free list has been initialized to point
490 -- to the next free node (via its Parent component), and the value 0
491 -- means that this is the last free node.
493 -- If Container.Free is negative, then the links on the free store
494 -- have not been initialized. In this case the link values are
495 -- implied: the free store comprises the components of the node array
496 -- started with the absolute value of Container.Free, and continuing
497 -- until the end of the array (Nodes'Last).
500 -- It might be possible to perform an optimization here. Suppose that
501 -- the free store can be represented as having two parts: one
502 -- comprising the non-contiguous inactive nodes linked together
503 -- in the normal way, and the other comprising the contiguous
504 -- inactive nodes (that are not linked together, at the end of the
505 -- nodes array). This would allow us to never have to initialize
506 -- the free store, except in a lazy way as nodes become inactive.
508 -- When an element is deleted from the list container, its node
509 -- becomes inactive, and so we set its Prev component to a negative
510 -- value, to indicate that it is now inactive. This provides a useful
511 -- way to detect a dangling cursor reference.
513 -- The comment above is incorrect; we need some other way to
514 -- indicate a node is inactive, for example by using a special
515 -- Color_Type value. ???
516 -- N (X).Prev := -1; -- Node is deallocated (not on active list)
518 if Tree
.Free
>= 0 then
519 -- The free store has previously been initialized. All we need to
520 -- do here is link the newly-free'd node onto the free list.
522 Set_Parent
(N
(X
), Tree
.Free
);
525 elsif X
+ 1 = abs Tree
.Free
then
526 -- The free store has not been initialized, and the node becoming
527 -- inactive immediately precedes the start of the free store. All
528 -- we need to do is move the start of the free store back by one.
530 Tree
.Free
:= Tree
.Free
+ 1;
533 -- The free store has not been initialized, and the node becoming
534 -- inactive does not immediately precede the free store. Here we
535 -- first initialize the free store (meaning the links are given
536 -- values in the traditional way), and then link the newly-free'd
537 -- node onto the head of the free store.
540 -- See the comments above for an optimization opportunity. If the
541 -- next link for a node on the free store is negative, then this
542 -- means the remaining nodes on the free store are physically
543 -- contiguous, starting as the absolute value of that index value.
545 Tree
.Free
:= abs Tree
.Free
;
547 if Tree
.Free
> Tree
.Capacity
then
551 for I
in Tree
.Free
.. Tree
.Capacity
- 1 loop
552 Set_Parent
(N
(I
), I
+ 1);
555 Set_Parent
(N
(Tree
.Capacity
), 0);
558 Set_Parent
(N
(X
), Tree
.Free
);
563 -----------------------
564 -- Generic_Allocate --
565 -----------------------
567 procedure Generic_Allocate
568 (Tree
: in out Tree_Type
'Class;
569 Node
: out Count_Type
)
571 N
: Nodes_Type
renames Tree
.Nodes
;
574 if Tree
.Free
>= 0 then
577 -- We always perform the assignment first, before we
578 -- change container state, in order to defend against
579 -- exceptions duration assignment.
581 Set_Element
(N
(Node
));
582 Tree
.Free
:= Parent
(N
(Node
));
585 -- A negative free store value means that the links of the nodes
586 -- in the free store have not been initialized. In this case, the
587 -- nodes are physically contiguous in the array, starting at the
588 -- index that is the absolute value of the Container.Free, and
589 -- continuing until the end of the array (Nodes'Last).
591 Node
:= abs Tree
.Free
;
593 -- As above, we perform this assignment first, before modifying
594 -- any container state.
596 Set_Element
(N
(Node
));
597 Tree
.Free
:= Tree
.Free
- 1;
600 -- When a node is allocated from the free store, its pointer components
601 -- (the links to other nodes in the tree) must also be initialized (to
602 -- 0, the equivalent of null). This simplifies the post-allocation
603 -- handling of nodes inserted into terminal positions.
605 Set_Parent
(N
(Node
), Parent
=> 0);
606 Set_Left
(N
(Node
), Left
=> 0);
607 Set_Right
(N
(Node
), Right
=> 0);
608 end Generic_Allocate
;
614 function Generic_Equal
(Left
, Right
: Tree_Type
'Class) return Boolean is
615 BL
: Natural renames Left
'Unrestricted_Access.Busy
;
616 LL
: Natural renames Left
'Unrestricted_Access.Lock
;
618 BR
: Natural renames Right
'Unrestricted_Access.Busy
;
619 LR
: Natural renames Right
'Unrestricted_Access.Lock
;
627 if Left
'Address = Right
'Address then
631 if Left
.Length
/= Right
.Length
then
635 -- If the containers are empty, return a result immediately, so as to
636 -- not manipulate the tamper bits unnecessarily.
638 if Left
.Length
= 0 then
642 -- Per AI05-0022, the container implementation is required to detect
643 -- element tampering by a generic actual subprogram.
651 L_Node
:= Left
.First
;
652 R_Node
:= Right
.First
;
654 while L_Node
/= 0 loop
655 if not Is_Equal
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
660 L_Node
:= Next
(Left
, L_Node
);
661 R_Node
:= Next
(Right
, R_Node
);
683 -----------------------
684 -- Generic_Iteration --
685 -----------------------
687 procedure Generic_Iteration
(Tree
: Tree_Type
'Class) is
688 procedure Iterate
(P
: Count_Type
);
694 procedure Iterate
(P
: Count_Type
) is
698 Iterate
(Left
(Tree
.Nodes
(X
)));
700 X
:= Right
(Tree
.Nodes
(X
));
704 -- Start of processing for Generic_Iteration
708 end Generic_Iteration
;
714 procedure Generic_Read
715 (Stream
: not null access Root_Stream_Type
'Class;
716 Tree
: in out Tree_Type
'Class)
718 Len
: Count_Type
'Base;
720 Node
, Last_Node
: Count_Type
;
722 N
: Nodes_Type
renames Tree
.Nodes
;
726 Count_Type
'Base'Read (Stream, Len);
729 raise Program_Error with "bad container length (corrupt stream)";
736 if Len > Tree.Capacity then
737 raise Constraint_Error with "length exceeds capacity";
740 -- Use Unconditional_Insert_With_Hint here instead ???
742 Allocate (Tree, Node);
743 pragma Assert (Node /= 0);
745 Set_Color (N (Node), Black);
752 for J in Count_Type range 2 .. Len loop
754 pragma Assert (Last_Node = Tree.Last);
756 Allocate (Tree, Node);
757 pragma Assert (Node /= 0);
759 Set_Color (N (Node), Red);
760 Set_Right (N (Last_Node), Right => Node);
762 Set_Parent (N (Node), Parent => Last_Node);
764 Rebalance_For_Insert (Tree, Node);
765 Tree.Length := Tree.Length + 1;
769 -------------------------------
770 -- Generic_Reverse_Iteration --
771 -------------------------------
773 procedure Generic_Reverse_Iteration (Tree : Tree_Type'Class) is
774 procedure Iterate (P : Count_Type);
780 procedure Iterate (P : Count_Type) is
784 Iterate (Right (Tree.Nodes (X)));
786 X := Left (Tree.Nodes (X));
790 -- Start of processing for Generic_Reverse_Iteration
794 end Generic_Reverse_Iteration;
800 procedure Generic_Write
801 (Stream : not null access Root_Stream_Type'Class;
802 Tree : Tree_Type'Class)
804 procedure Process (Node : Count_Type);
805 pragma Inline (Process);
807 procedure Iterate is new Generic_Iteration (Process);
813 procedure Process (Node : Count_Type) is
815 Write_Node (Stream, Tree.Nodes (Node));
818 -- Start of processing for Generic_Write
821 Count_Type'Base'Write
(Stream
, Tree
.Length
);
829 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
) is
833 N
: Nodes_Type
renames Tree
.Nodes
;
835 Y
: constant Count_Type
:= Right
(N
(X
));
836 pragma Assert
(Y
/= 0);
839 Set_Right
(N
(X
), Left
(N
(Y
)));
841 if Left
(N
(Y
)) /= 0 then
842 Set_Parent
(N
(Left
(N
(Y
))), X
);
845 Set_Parent
(N
(Y
), Parent
(N
(X
)));
847 if X
= Tree
.Root
then
849 elsif X
= Left
(N
(Parent
(N
(X
)))) then
850 Set_Left
(N
(Parent
(N
(X
))), Y
);
852 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
853 Set_Right
(N
(Parent
(N
(X
))), Y
);
857 Set_Parent
(N
(X
), Y
);
865 (Tree
: Tree_Type
'Class;
866 Node
: Count_Type
) return Count_Type
870 X
: Count_Type
:= Node
;
875 Y
:= Right
(Tree
.Nodes
(X
));
890 (Tree
: Tree_Type
'Class;
891 Node
: Count_Type
) return Count_Type
895 X
: Count_Type
:= Node
;
900 Y
:= Left
(Tree
.Nodes
(X
));
915 (Tree
: Tree_Type
'Class;
916 Node
: Count_Type
) return Count_Type
925 if Right
(Tree
.Nodes
(Node
)) /= 0 then
926 return Min
(Tree
, Right
(Tree
.Nodes
(Node
)));
930 X
: Count_Type
:= Node
;
931 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
934 while Y
/= 0 and then X
= Right
(Tree
.Nodes
(Y
)) loop
936 Y
:= Parent
(Tree
.Nodes
(Y
));
948 (Tree
: Tree_Type
'Class;
949 Node
: Count_Type
) return Count_Type
956 if Left
(Tree
.Nodes
(Node
)) /= 0 then
957 return Max
(Tree
, Left
(Tree
.Nodes
(Node
)));
961 X
: Count_Type
:= Node
;
962 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
965 while Y
/= 0 and then X
= Left
(Tree
.Nodes
(Y
)) loop
967 Y
:= Parent
(Tree
.Nodes
(Y
));
974 --------------------------
975 -- Rebalance_For_Insert --
976 --------------------------
978 procedure Rebalance_For_Insert
979 (Tree
: in out Tree_Type
'Class;
984 N
: Nodes_Type
renames Tree
.Nodes
;
986 X
: Count_Type
:= Node
;
987 pragma Assert
(X
/= 0);
988 pragma Assert
(Color
(N
(X
)) = Red
);
993 while X
/= Tree
.Root
and then Color
(N
(Parent
(N
(X
)))) = Red
loop
994 if Parent
(N
(X
)) = Left
(N
(Parent
(N
(Parent
(N
(X
)))))) then
995 Y
:= Right
(N
(Parent
(N
(Parent
(N
(X
))))));
997 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
998 Set_Color
(N
(Parent
(N
(X
))), Black
);
999 Set_Color
(N
(Y
), Black
);
1000 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
1001 X
:= Parent
(N
(Parent
(N
(X
))));
1004 if X
= Right
(N
(Parent
(N
(X
)))) then
1005 X
:= Parent
(N
(X
));
1006 Left_Rotate
(Tree
, X
);
1009 Set_Color
(N
(Parent
(N
(X
))), Black
);
1010 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
1011 Right_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
1015 pragma Assert
(Parent
(N
(X
)) =
1016 Right
(N
(Parent
(N
(Parent
(N
(X
)))))));
1018 Y
:= Left
(N
(Parent
(N
(Parent
(N
(X
))))));
1020 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
1021 Set_Color
(N
(Parent
(N
(X
))), Black
);
1022 Set_Color
(N
(Y
), Black
);
1023 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
1024 X
:= Parent
(N
(Parent
(N
(X
))));
1027 if X
= Left
(N
(Parent
(N
(X
)))) then
1028 X
:= Parent
(N
(X
));
1029 Right_Rotate
(Tree
, X
);
1032 Set_Color
(N
(Parent
(N
(X
))), Black
);
1033 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
1034 Left_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
1039 Set_Color
(N
(Tree
.Root
), Black
);
1040 end Rebalance_For_Insert
;
1046 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
) is
1047 N
: Nodes_Type
renames Tree
.Nodes
;
1049 X
: constant Count_Type
:= Left
(N
(Y
));
1050 pragma Assert
(X
/= 0);
1053 Set_Left
(N
(Y
), Right
(N
(X
)));
1055 if Right
(N
(X
)) /= 0 then
1056 Set_Parent
(N
(Right
(N
(X
))), Y
);
1059 Set_Parent
(N
(X
), Parent
(N
(Y
)));
1061 if Y
= Tree
.Root
then
1063 elsif Y
= Left
(N
(Parent
(N
(Y
)))) then
1064 Set_Left
(N
(Parent
(N
(Y
))), X
);
1066 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
1067 Set_Right
(N
(Parent
(N
(Y
))), X
);
1070 Set_Right
(N
(X
), Y
);
1071 Set_Parent
(N
(Y
), X
);
1078 function Vet
(Tree
: Tree_Type
'Class; Index
: Count_Type
) return Boolean is
1079 Nodes
: Nodes_Type
renames Tree
.Nodes
;
1080 Node
: Node_Type
renames Nodes
(Index
);
1083 if Parent
(Node
) = Index
1084 or else Left
(Node
) = Index
1085 or else Right
(Node
) = Index
1091 or else Tree
.Root
= 0
1092 or else Tree
.First
= 0
1093 or else Tree
.Last
= 0
1098 if Parent
(Nodes
(Tree
.Root
)) /= 0 then
1102 if Left
(Nodes
(Tree
.First
)) /= 0 then
1106 if Right
(Nodes
(Tree
.Last
)) /= 0 then
1110 if Tree
.Length
= 1 then
1111 if Tree
.First
/= Tree
.Last
1112 or else Tree
.First
/= Tree
.Root
1117 if Index
/= Tree
.First
then
1121 if Parent
(Node
) /= 0
1122 or else Left
(Node
) /= 0
1123 or else Right
(Node
) /= 0
1131 if Tree
.First
= Tree
.Last
then
1135 if Tree
.Length
= 2 then
1136 if Tree
.First
/= Tree
.Root
and then Tree
.Last
/= Tree
.Root
then
1140 if Tree
.First
/= Index
and then Tree
.Last
/= Index
then
1145 if Left
(Node
) /= 0 and then Parent
(Nodes
(Left
(Node
))) /= Index
then
1149 if Right
(Node
) /= 0 and then Parent
(Nodes
(Right
(Node
))) /= Index
then
1153 if Parent
(Node
) = 0 then
1154 if Tree
.Root
/= Index
then
1158 elsif Left
(Nodes
(Parent
(Node
))) /= Index
1159 and then Right
(Nodes
(Parent
(Node
))) /= Index
1167 end Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
;