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 -----------------------
43 -- Local Subprograms --
44 -----------------------
46 procedure Delete_Fixup
(Tree
: in out Tree_Type
'Class; Node
: Count_Type
);
47 procedure Delete_Swap
(Tree
: in out Tree_Type
'Class; Z
, Y
: Count_Type
);
49 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
);
50 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
);
56 procedure Clear_Tree
(Tree
: in out Tree_Type
'Class) is
59 raise Program_Error
with
60 "attempt to tamper with cursors (container is busy)";
63 -- The lock status (which monitors "element tampering") always implies
64 -- that the busy status (which monitors "cursor tampering") is set too;
65 -- this is a representation invariant. Thus if the busy bit is not set,
66 -- then the lock bit must not be set either.
68 pragma Assert
(Tree
.Lock
= 0);
81 procedure Delete_Fixup
82 (Tree
: in out Tree_Type
'Class;
89 N
: Nodes_Type
renames Tree
.Nodes
;
93 while X
/= Tree
.Root
and then Color
(N
(X
)) = Black
loop
94 if X
= Left
(N
(Parent
(N
(X
)))) then
95 W
:= Right
(N
(Parent
(N
(X
))));
97 if Color
(N
(W
)) = Red
then
98 Set_Color
(N
(W
), Black
);
99 Set_Color
(N
(Parent
(N
(X
))), Red
);
100 Left_Rotate
(Tree
, Parent
(N
(X
)));
101 W
:= Right
(N
(Parent
(N
(X
))));
104 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
106 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
108 Set_Color
(N
(W
), Red
);
113 or else Color
(N
(Right
(N
(W
)))) = Black
115 -- As a condition for setting the color of the left child to
116 -- black, the left child access value must be non-null. A
117 -- truth table analysis shows that if we arrive here, that
118 -- condition holds, so there's no need for an explicit test.
119 -- The assertion is here to document what we know is true.
121 pragma Assert
(Left
(N
(W
)) /= 0);
122 Set_Color
(N
(Left
(N
(W
))), Black
);
124 Set_Color
(N
(W
), Red
);
125 Right_Rotate
(Tree
, W
);
126 W
:= Right
(N
(Parent
(N
(X
))));
129 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
130 Set_Color
(N
(Parent
(N
(X
))), Black
);
131 Set_Color
(N
(Right
(N
(W
))), Black
);
132 Left_Rotate
(Tree
, Parent
(N
(X
)));
137 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
139 W
:= Left
(N
(Parent
(N
(X
))));
141 if Color
(N
(W
)) = Red
then
142 Set_Color
(N
(W
), Black
);
143 Set_Color
(N
(Parent
(N
(X
))), Red
);
144 Right_Rotate
(Tree
, Parent
(N
(X
)));
145 W
:= Left
(N
(Parent
(N
(X
))));
148 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
150 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
152 Set_Color
(N
(W
), Red
);
157 or else Color
(N
(Left
(N
(W
)))) = Black
159 -- As a condition for setting the color of the right child
160 -- to black, the right child access value must be non-null.
161 -- A truth table analysis shows that if we arrive here, that
162 -- condition holds, so there's no need for an explicit test.
163 -- The assertion is here to document what we know is true.
165 pragma Assert
(Right
(N
(W
)) /= 0);
166 Set_Color
(N
(Right
(N
(W
))), Black
);
168 Set_Color
(N
(W
), Red
);
169 Left_Rotate
(Tree
, W
);
170 W
:= Left
(N
(Parent
(N
(X
))));
173 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
174 Set_Color
(N
(Parent
(N
(X
))), Black
);
175 Set_Color
(N
(Left
(N
(W
))), Black
);
176 Right_Rotate
(Tree
, Parent
(N
(X
)));
182 Set_Color
(N
(X
), Black
);
185 ---------------------------
186 -- Delete_Node_Sans_Free --
187 ---------------------------
189 procedure Delete_Node_Sans_Free
190 (Tree
: in out Tree_Type
'Class;
197 Z
: constant Count_Type
:= Node
;
199 N
: Nodes_Type
renames Tree
.Nodes
;
202 if Tree
.Busy
> 0 then
203 raise Program_Error
with
204 "attempt to tamper with cursors (container is busy)";
207 -- If node is not present, return (exception will be raised in caller)
213 pragma Assert
(Tree
.Length
> 0);
214 pragma Assert
(Tree
.Root
/= 0);
215 pragma Assert
(Tree
.First
/= 0);
216 pragma Assert
(Tree
.Last
/= 0);
217 pragma Assert
(Parent
(N
(Tree
.Root
)) = 0);
219 pragma Assert
((Tree
.Length
> 1)
220 or else (Tree
.First
= Tree
.Last
221 and then Tree
.First
= Tree
.Root
));
223 pragma Assert
((Left
(N
(Node
)) = 0)
224 or else (Parent
(N
(Left
(N
(Node
)))) = Node
));
226 pragma Assert
((Right
(N
(Node
)) = 0)
227 or else (Parent
(N
(Right
(N
(Node
)))) = Node
));
229 pragma Assert
(((Parent
(N
(Node
)) = 0) and then (Tree
.Root
= Node
))
230 or else ((Parent
(N
(Node
)) /= 0) and then
231 ((Left
(N
(Parent
(N
(Node
)))) = Node
)
233 (Right
(N
(Parent
(N
(Node
)))) = Node
))));
235 if Left
(N
(Z
)) = 0 then
236 if Right
(N
(Z
)) = 0 then
237 if Z
= Tree
.First
then
238 Tree
.First
:= Parent
(N
(Z
));
241 if Z
= Tree
.Last
then
242 Tree
.Last
:= Parent
(N
(Z
));
245 if Color
(N
(Z
)) = Black
then
246 Delete_Fixup
(Tree
, Z
);
249 pragma Assert
(Left
(N
(Z
)) = 0);
250 pragma Assert
(Right
(N
(Z
)) = 0);
252 if Z
= Tree
.Root
then
253 pragma Assert
(Tree
.Length
= 1);
254 pragma Assert
(Parent
(N
(Z
)) = 0);
256 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
257 Set_Left
(N
(Parent
(N
(Z
))), 0);
259 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
260 Set_Right
(N
(Parent
(N
(Z
))), 0);
264 pragma Assert
(Z
/= Tree
.Last
);
268 if Z
= Tree
.First
then
269 Tree
.First
:= Min
(Tree
, X
);
272 if Z
= Tree
.Root
then
274 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
275 Set_Left
(N
(Parent
(N
(Z
))), X
);
277 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
278 Set_Right
(N
(Parent
(N
(Z
))), X
);
281 Set_Parent
(N
(X
), Parent
(N
(Z
)));
283 if Color
(N
(Z
)) = Black
then
284 Delete_Fixup
(Tree
, X
);
288 elsif Right
(N
(Z
)) = 0 then
289 pragma Assert
(Z
/= Tree
.First
);
293 if Z
= Tree
.Last
then
294 Tree
.Last
:= Max
(Tree
, X
);
297 if Z
= Tree
.Root
then
299 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
300 Set_Left
(N
(Parent
(N
(Z
))), X
);
302 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
303 Set_Right
(N
(Parent
(N
(Z
))), X
);
306 Set_Parent
(N
(X
), Parent
(N
(Z
)));
308 if Color
(N
(Z
)) = Black
then
309 Delete_Fixup
(Tree
, X
);
313 pragma Assert
(Z
/= Tree
.First
);
314 pragma Assert
(Z
/= Tree
.Last
);
317 pragma Assert
(Left
(N
(Y
)) = 0);
322 if Y
= Left
(N
(Parent
(N
(Y
)))) then
323 pragma Assert
(Parent
(N
(Y
)) /= Z
);
324 Delete_Swap
(Tree
, Z
, Y
);
325 Set_Left
(N
(Parent
(N
(Z
))), Z
);
328 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
329 pragma Assert
(Parent
(N
(Y
)) = Z
);
330 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
332 if Z
= Tree
.Root
then
334 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
335 Set_Left
(N
(Parent
(N
(Z
))), Y
);
337 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
338 Set_Right
(N
(Parent
(N
(Z
))), Y
);
341 Set_Left
(N
(Y
), Left
(N
(Z
)));
342 Set_Parent
(N
(Left
(N
(Y
))), Y
);
343 Set_Right
(N
(Y
), Z
);
345 Set_Parent
(N
(Z
), Y
);
347 Set_Right
(N
(Z
), 0);
350 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
352 Set_Color
(N
(Y
), Color
(N
(Z
)));
353 Set_Color
(N
(Z
), Y_Color
);
357 if Color
(N
(Z
)) = Black
then
358 Delete_Fixup
(Tree
, Z
);
361 pragma Assert
(Left
(N
(Z
)) = 0);
362 pragma Assert
(Right
(N
(Z
)) = 0);
364 if Z
= Right
(N
(Parent
(N
(Z
)))) then
365 Set_Right
(N
(Parent
(N
(Z
))), 0);
367 pragma Assert
(Z
= Left
(N
(Parent
(N
(Z
)))));
368 Set_Left
(N
(Parent
(N
(Z
))), 0);
372 if Y
= Left
(N
(Parent
(N
(Y
)))) then
373 pragma Assert
(Parent
(N
(Y
)) /= Z
);
375 Delete_Swap
(Tree
, Z
, Y
);
377 Set_Left
(N
(Parent
(N
(Z
))), X
);
378 Set_Parent
(N
(X
), Parent
(N
(Z
)));
381 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
382 pragma Assert
(Parent
(N
(Y
)) = Z
);
384 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
386 if Z
= Tree
.Root
then
388 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
389 Set_Left
(N
(Parent
(N
(Z
))), Y
);
391 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
392 Set_Right
(N
(Parent
(N
(Z
))), Y
);
395 Set_Left
(N
(Y
), Left
(N
(Z
)));
396 Set_Parent
(N
(Left
(N
(Y
))), Y
);
399 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
401 Set_Color
(N
(Y
), Color
(N
(Z
)));
402 Set_Color
(N
(Z
), Y_Color
);
406 if Color
(N
(Z
)) = Black
then
407 Delete_Fixup
(Tree
, X
);
412 Tree
.Length
:= Tree
.Length
- 1;
413 end Delete_Node_Sans_Free
;
419 procedure Delete_Swap
420 (Tree
: in out Tree_Type
'Class;
423 N
: Nodes_Type
renames Tree
.Nodes
;
425 pragma Assert
(Z
/= Y
);
426 pragma Assert
(Parent
(N
(Y
)) /= Z
);
428 Y_Parent
: constant Count_Type
:= Parent
(N
(Y
));
429 Y_Color
: constant Color_Type
:= Color
(N
(Y
));
432 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
433 Set_Left
(N
(Y
), Left
(N
(Z
)));
434 Set_Right
(N
(Y
), Right
(N
(Z
)));
435 Set_Color
(N
(Y
), Color
(N
(Z
)));
437 if Tree
.Root
= Z
then
439 elsif Right
(N
(Parent
(N
(Y
)))) = Z
then
440 Set_Right
(N
(Parent
(N
(Y
))), Y
);
442 pragma Assert
(Left
(N
(Parent
(N
(Y
)))) = Z
);
443 Set_Left
(N
(Parent
(N
(Y
))), Y
);
446 if Right
(N
(Y
)) /= 0 then
447 Set_Parent
(N
(Right
(N
(Y
))), Y
);
450 if Left
(N
(Y
)) /= 0 then
451 Set_Parent
(N
(Left
(N
(Y
))), Y
);
454 Set_Parent
(N
(Z
), Y_Parent
);
455 Set_Color
(N
(Z
), Y_Color
);
457 Set_Right
(N
(Z
), 0);
464 procedure Free
(Tree
: in out Tree_Type
'Class; X
: Count_Type
) is
465 pragma Assert
(X
> 0);
466 pragma Assert
(X
<= Tree
.Capacity
);
468 N
: Nodes_Type
renames Tree
.Nodes
;
469 -- pragma Assert (N (X).Prev >= 0); -- node is active
470 -- Find a way to mark a node as active vs. inactive; we could
471 -- use a special value in Color_Type for this. ???
474 -- The set container actually contains two data structures: a list for
475 -- the "active" nodes that contain elements that have been inserted
476 -- onto the tree, and another for the "inactive" nodes of the free
479 -- We desire that merely declaring an object should have only minimal
480 -- cost; specially, we want to avoid having to initialize the free
481 -- store (to fill in the links), especially if the capacity is large.
483 -- The head of the free list is indicated by Container.Free. If its
484 -- value is non-negative, then the free store has been initialized
485 -- in the "normal" way: Container.Free points to the head of the list
486 -- of free (inactive) nodes, and the value 0 means the free list is
487 -- empty. Each node on the free list has been initialized to point
488 -- to the next free node (via its Parent component), and the value 0
489 -- means that this is the last free node.
491 -- If Container.Free is negative, then the links on the free store
492 -- have not been initialized. In this case the link values are
493 -- implied: the free store comprises the components of the node array
494 -- started with the absolute value of Container.Free, and continuing
495 -- until the end of the array (Nodes'Last).
498 -- It might be possible to perform an optimization here. Suppose that
499 -- the free store can be represented as having two parts: one
500 -- comprising the non-contiguous inactive nodes linked together
501 -- in the normal way, and the other comprising the contiguous
502 -- inactive nodes (that are not linked together, at the end of the
503 -- nodes array). This would allow us to never have to initialize
504 -- the free store, except in a lazy way as nodes become inactive.
506 -- When an element is deleted from the list container, its node
507 -- becomes inactive, and so we set its Prev component to a negative
508 -- value, to indicate that it is now inactive. This provides a useful
509 -- way to detect a dangling cursor reference.
511 -- The comment above is incorrect; we need some other way to
512 -- indicate a node is inactive, for example by using a special
513 -- Color_Type value. ???
514 -- N (X).Prev := -1; -- Node is deallocated (not on active list)
516 if Tree
.Free
>= 0 then
517 -- The free store has previously been initialized. All we need to
518 -- do here is link the newly-free'd node onto the free list.
520 Set_Parent
(N
(X
), Tree
.Free
);
523 elsif X
+ 1 = abs Tree
.Free
then
524 -- The free store has not been initialized, and the node becoming
525 -- inactive immediately precedes the start of the free store. All
526 -- we need to do is move the start of the free store back by one.
528 Tree
.Free
:= Tree
.Free
+ 1;
531 -- The free store has not been initialized, and the node becoming
532 -- inactive does not immediately precede the free store. Here we
533 -- first initialize the free store (meaning the links are given
534 -- values in the traditional way), and then link the newly-free'd
535 -- node onto the head of the free store.
538 -- See the comments above for an optimization opportunity. If the
539 -- next link for a node on the free store is negative, then this
540 -- means the remaining nodes on the free store are physically
541 -- contiguous, starting as the absolute value of that index value.
543 Tree
.Free
:= abs Tree
.Free
;
545 if Tree
.Free
> Tree
.Capacity
then
549 for I
in Tree
.Free
.. Tree
.Capacity
- 1 loop
550 Set_Parent
(N
(I
), I
+ 1);
553 Set_Parent
(N
(Tree
.Capacity
), 0);
556 Set_Parent
(N
(X
), Tree
.Free
);
561 -----------------------
562 -- Generic_Allocate --
563 -----------------------
565 procedure Generic_Allocate
566 (Tree
: in out Tree_Type
'Class;
567 Node
: out Count_Type
)
569 N
: Nodes_Type
renames Tree
.Nodes
;
572 if Tree
.Free
>= 0 then
575 -- We always perform the assignment first, before we
576 -- change container state, in order to defend against
577 -- exceptions duration assignment.
579 Set_Element
(N
(Node
));
580 Tree
.Free
:= Parent
(N
(Node
));
583 -- A negative free store value means that the links of the nodes
584 -- in the free store have not been initialized. In this case, the
585 -- nodes are physically contiguous in the array, starting at the
586 -- index that is the absolute value of the Container.Free, and
587 -- continuing until the end of the array (Nodes'Last).
589 Node
:= abs Tree
.Free
;
591 -- As above, we perform this assignment first, before modifying
592 -- any container state.
594 Set_Element
(N
(Node
));
595 Tree
.Free
:= Tree
.Free
- 1;
598 -- When a node is allocated from the free store, its pointer components
599 -- (the links to other nodes in the tree) must also be initialized (to
600 -- 0, the equivalent of null). This simplifies the post-allocation
601 -- handling of nodes inserted into terminal positions.
603 Set_Parent
(N
(Node
), Parent
=> 0);
604 Set_Left
(N
(Node
), Left
=> 0);
605 Set_Right
(N
(Node
), Right
=> 0);
606 end Generic_Allocate
;
612 function Generic_Equal
(Left
, Right
: Tree_Type
'Class) return Boolean is
613 BL
: Natural renames Left
'Unrestricted_Access.Busy
;
614 LL
: Natural renames Left
'Unrestricted_Access.Lock
;
616 BR
: Natural renames Right
'Unrestricted_Access.Busy
;
617 LR
: Natural renames Right
'Unrestricted_Access.Lock
;
625 if Left
'Address = Right
'Address then
629 if Left
.Length
/= Right
.Length
then
633 -- If the containers are empty, return a result immediately, so as to
634 -- not manipulate the tamper bits unnecessarily.
636 if Left
.Length
= 0 then
640 -- Per AI05-0022, the container implementation is required to detect
641 -- element tampering by a generic actual subprogram.
649 L_Node
:= Left
.First
;
650 R_Node
:= Right
.First
;
652 while L_Node
/= 0 loop
653 if not Is_Equal
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
658 L_Node
:= Next
(Left
, L_Node
);
659 R_Node
:= Next
(Right
, R_Node
);
681 -----------------------
682 -- Generic_Iteration --
683 -----------------------
685 procedure Generic_Iteration
(Tree
: Tree_Type
'Class) is
686 procedure Iterate
(P
: Count_Type
);
692 procedure Iterate
(P
: Count_Type
) is
696 Iterate
(Left
(Tree
.Nodes
(X
)));
698 X
:= Right
(Tree
.Nodes
(X
));
702 -- Start of processing for Generic_Iteration
706 end Generic_Iteration
;
712 procedure Generic_Read
713 (Stream
: not null access Root_Stream_Type
'Class;
714 Tree
: in out Tree_Type
'Class)
716 Len
: Count_Type
'Base;
718 Node
, Last_Node
: Count_Type
;
720 N
: Nodes_Type
renames Tree
.Nodes
;
724 Count_Type
'Base'Read (Stream, Len);
727 raise Program_Error with "bad container length (corrupt stream)";
734 if Len > Tree.Capacity then
735 raise Constraint_Error with "length exceeds capacity";
738 -- Use Unconditional_Insert_With_Hint here instead ???
740 Allocate (Tree, Node);
741 pragma Assert (Node /= 0);
743 Set_Color (N (Node), Black);
750 for J in Count_Type range 2 .. Len loop
752 pragma Assert (Last_Node = Tree.Last);
754 Allocate (Tree, Node);
755 pragma Assert (Node /= 0);
757 Set_Color (N (Node), Red);
758 Set_Right (N (Last_Node), Right => Node);
760 Set_Parent (N (Node), Parent => Last_Node);
762 Rebalance_For_Insert (Tree, Node);
763 Tree.Length := Tree.Length + 1;
767 -------------------------------
768 -- Generic_Reverse_Iteration --
769 -------------------------------
771 procedure Generic_Reverse_Iteration (Tree : Tree_Type'Class) is
772 procedure Iterate (P : Count_Type);
778 procedure Iterate (P : Count_Type) is
782 Iterate (Right (Tree.Nodes (X)));
784 X := Left (Tree.Nodes (X));
788 -- Start of processing for Generic_Reverse_Iteration
792 end Generic_Reverse_Iteration;
798 procedure Generic_Write
799 (Stream : not null access Root_Stream_Type'Class;
800 Tree : Tree_Type'Class)
802 procedure Process (Node : Count_Type);
803 pragma Inline (Process);
805 procedure Iterate is new Generic_Iteration (Process);
811 procedure Process (Node : Count_Type) is
813 Write_Node (Stream, Tree.Nodes (Node));
816 -- Start of processing for Generic_Write
819 Count_Type'Base'Write
(Stream
, Tree
.Length
);
827 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
) is
831 N
: Nodes_Type
renames Tree
.Nodes
;
833 Y
: constant Count_Type
:= Right
(N
(X
));
834 pragma Assert
(Y
/= 0);
837 Set_Right
(N
(X
), Left
(N
(Y
)));
839 if Left
(N
(Y
)) /= 0 then
840 Set_Parent
(N
(Left
(N
(Y
))), X
);
843 Set_Parent
(N
(Y
), Parent
(N
(X
)));
845 if X
= Tree
.Root
then
847 elsif X
= Left
(N
(Parent
(N
(X
)))) then
848 Set_Left
(N
(Parent
(N
(X
))), Y
);
850 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
851 Set_Right
(N
(Parent
(N
(X
))), Y
);
855 Set_Parent
(N
(X
), Y
);
863 (Tree
: Tree_Type
'Class;
864 Node
: Count_Type
) return Count_Type
868 X
: Count_Type
:= Node
;
873 Y
:= Right
(Tree
.Nodes
(X
));
888 (Tree
: Tree_Type
'Class;
889 Node
: Count_Type
) return Count_Type
893 X
: Count_Type
:= Node
;
898 Y
:= Left
(Tree
.Nodes
(X
));
913 (Tree
: Tree_Type
'Class;
914 Node
: Count_Type
) return Count_Type
923 if Right
(Tree
.Nodes
(Node
)) /= 0 then
924 return Min
(Tree
, Right
(Tree
.Nodes
(Node
)));
928 X
: Count_Type
:= Node
;
929 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
932 while Y
/= 0 and then X
= Right
(Tree
.Nodes
(Y
)) loop
934 Y
:= Parent
(Tree
.Nodes
(Y
));
946 (Tree
: Tree_Type
'Class;
947 Node
: Count_Type
) return Count_Type
954 if Left
(Tree
.Nodes
(Node
)) /= 0 then
955 return Max
(Tree
, Left
(Tree
.Nodes
(Node
)));
959 X
: Count_Type
:= Node
;
960 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
963 while Y
/= 0 and then X
= Left
(Tree
.Nodes
(Y
)) loop
965 Y
:= Parent
(Tree
.Nodes
(Y
));
972 --------------------------
973 -- Rebalance_For_Insert --
974 --------------------------
976 procedure Rebalance_For_Insert
977 (Tree
: in out Tree_Type
'Class;
982 N
: Nodes_Type
renames Tree
.Nodes
;
984 X
: Count_Type
:= Node
;
985 pragma Assert
(X
/= 0);
986 pragma Assert
(Color
(N
(X
)) = Red
);
991 while X
/= Tree
.Root
and then Color
(N
(Parent
(N
(X
)))) = Red
loop
992 if Parent
(N
(X
)) = Left
(N
(Parent
(N
(Parent
(N
(X
)))))) then
993 Y
:= Right
(N
(Parent
(N
(Parent
(N
(X
))))));
995 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
996 Set_Color
(N
(Parent
(N
(X
))), Black
);
997 Set_Color
(N
(Y
), Black
);
998 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
999 X
:= Parent
(N
(Parent
(N
(X
))));
1002 if X
= Right
(N
(Parent
(N
(X
)))) then
1003 X
:= Parent
(N
(X
));
1004 Left_Rotate
(Tree
, X
);
1007 Set_Color
(N
(Parent
(N
(X
))), Black
);
1008 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
1009 Right_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
1013 pragma Assert
(Parent
(N
(X
)) =
1014 Right
(N
(Parent
(N
(Parent
(N
(X
)))))));
1016 Y
:= Left
(N
(Parent
(N
(Parent
(N
(X
))))));
1018 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
1019 Set_Color
(N
(Parent
(N
(X
))), Black
);
1020 Set_Color
(N
(Y
), Black
);
1021 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
1022 X
:= Parent
(N
(Parent
(N
(X
))));
1025 if X
= Left
(N
(Parent
(N
(X
)))) then
1026 X
:= Parent
(N
(X
));
1027 Right_Rotate
(Tree
, X
);
1030 Set_Color
(N
(Parent
(N
(X
))), Black
);
1031 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
1032 Left_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
1037 Set_Color
(N
(Tree
.Root
), Black
);
1038 end Rebalance_For_Insert
;
1044 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
) is
1045 N
: Nodes_Type
renames Tree
.Nodes
;
1047 X
: constant Count_Type
:= Left
(N
(Y
));
1048 pragma Assert
(X
/= 0);
1051 Set_Left
(N
(Y
), Right
(N
(X
)));
1053 if Right
(N
(X
)) /= 0 then
1054 Set_Parent
(N
(Right
(N
(X
))), Y
);
1057 Set_Parent
(N
(X
), Parent
(N
(Y
)));
1059 if Y
= Tree
.Root
then
1061 elsif Y
= Left
(N
(Parent
(N
(Y
)))) then
1062 Set_Left
(N
(Parent
(N
(Y
))), X
);
1064 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
1065 Set_Right
(N
(Parent
(N
(Y
))), X
);
1068 Set_Right
(N
(X
), Y
);
1069 Set_Parent
(N
(Y
), X
);
1076 function Vet
(Tree
: Tree_Type
'Class; Index
: Count_Type
) return Boolean is
1077 Nodes
: Nodes_Type
renames Tree
.Nodes
;
1078 Node
: Node_Type
renames Nodes
(Index
);
1081 if Parent
(Node
) = Index
1082 or else Left
(Node
) = Index
1083 or else Right
(Node
) = Index
1089 or else Tree
.Root
= 0
1090 or else Tree
.First
= 0
1091 or else Tree
.Last
= 0
1096 if Parent
(Nodes
(Tree
.Root
)) /= 0 then
1100 if Left
(Nodes
(Tree
.First
)) /= 0 then
1104 if Right
(Nodes
(Tree
.Last
)) /= 0 then
1108 if Tree
.Length
= 1 then
1109 if Tree
.First
/= Tree
.Last
1110 or else Tree
.First
/= Tree
.Root
1115 if Index
/= Tree
.First
then
1119 if Parent
(Node
) /= 0
1120 or else Left
(Node
) /= 0
1121 or else Right
(Node
) /= 0
1129 if Tree
.First
= Tree
.Last
then
1133 if Tree
.Length
= 2 then
1134 if Tree
.First
/= Tree
.Root
and then Tree
.Last
/= Tree
.Root
then
1138 if Tree
.First
/= Index
and then Tree
.Last
/= Index
then
1143 if Left
(Node
) /= 0 and then Parent
(Nodes
(Left
(Node
))) /= Index
then
1147 if Right
(Node
) /= 0 and then Parent
(Nodes
(Right
(Node
))) /= Index
then
1151 if Parent
(Node
) = 0 then
1152 if Tree
.Root
/= Index
then
1156 elsif Left
(Nodes
(Parent
(Node
))) /= Index
1157 and then Right
(Nodes
(Parent
(Node
))) /= Index
1165 end Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
;