1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_BOUNDED_OPERATIONS --
9 -- Copyright (C) 2004-2010, 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_Bounded_Operations
is
41 -----------------------
42 -- Local Subprograms --
43 -----------------------
45 procedure Delete_Fixup
(Tree
: in out Tree_Type
'Class; Node
: Count_Type
);
46 procedure Delete_Swap
(Tree
: in out Tree_Type
'Class; Z
, Y
: Count_Type
);
48 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
);
49 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
);
55 procedure Clear_Tree
(Tree
: in out Tree_Type
'Class) is
58 raise Program_Error
with
59 "attempt to tamper with cursors (container is busy)";
75 procedure Delete_Fixup
76 (Tree
: in out Tree_Type
'Class;
84 N
: Nodes_Type
renames Tree
.Nodes
;
89 and then Color
(N
(X
)) = Black
91 if X
= Left
(N
(Parent
(N
(X
)))) then
92 W
:= Right
(N
(Parent
(N
(X
))));
94 if Color
(N
(W
)) = Red
then
95 Set_Color
(N
(W
), Black
);
96 Set_Color
(N
(Parent
(N
(X
))), Red
);
97 Left_Rotate
(Tree
, Parent
(N
(X
)));
98 W
:= Right
(N
(Parent
(N
(X
))));
101 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
103 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
105 Set_Color
(N
(W
), Red
);
110 or else Color
(N
(Right
(N
(W
)))) = Black
112 -- As a condition for setting the color of the left child to
113 -- black, the left child access value must be non-null. A
114 -- truth table analysis shows that if we arrive here, that
115 -- condition holds, so there's no need for an explicit test.
116 -- The assertion is here to document what we know is true.
118 pragma Assert
(Left
(N
(W
)) /= 0);
119 Set_Color
(N
(Left
(N
(W
))), Black
);
121 Set_Color
(N
(W
), Red
);
122 Right_Rotate
(Tree
, W
);
123 W
:= Right
(N
(Parent
(N
(X
))));
126 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
127 Set_Color
(N
(Parent
(N
(X
))), Black
);
128 Set_Color
(N
(Right
(N
(W
))), Black
);
129 Left_Rotate
(Tree
, Parent
(N
(X
)));
134 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
136 W
:= Left
(N
(Parent
(N
(X
))));
138 if Color
(N
(W
)) = Red
then
139 Set_Color
(N
(W
), Black
);
140 Set_Color
(N
(Parent
(N
(X
))), Red
);
141 Right_Rotate
(Tree
, Parent
(N
(X
)));
142 W
:= Left
(N
(Parent
(N
(X
))));
145 if (Left
(N
(W
)) = 0 or else Color
(N
(Left
(N
(W
)))) = Black
)
147 (Right
(N
(W
)) = 0 or else Color
(N
(Right
(N
(W
)))) = Black
)
149 Set_Color
(N
(W
), Red
);
154 or else Color
(N
(Left
(N
(W
)))) = Black
156 -- As a condition for setting the color of the right child
157 -- to black, the right child access value must be non-null.
158 -- A truth table analysis shows that if we arrive here, that
159 -- condition holds, so there's no need for an explicit test.
160 -- The assertion is here to document what we know is true.
162 pragma Assert
(Right
(N
(W
)) /= 0);
163 Set_Color
(N
(Right
(N
(W
))), Black
);
165 Set_Color
(N
(W
), Red
);
166 Left_Rotate
(Tree
, W
);
167 W
:= Left
(N
(Parent
(N
(X
))));
170 Set_Color
(N
(W
), Color
(N
(Parent
(N
(X
)))));
171 Set_Color
(N
(Parent
(N
(X
))), Black
);
172 Set_Color
(N
(Left
(N
(W
))), Black
);
173 Right_Rotate
(Tree
, Parent
(N
(X
)));
179 Set_Color
(N
(X
), Black
);
182 ---------------------------
183 -- Delete_Node_Sans_Free --
184 ---------------------------
186 procedure Delete_Node_Sans_Free
187 (Tree
: in out Tree_Type
'Class;
194 Z
: constant Count_Type
:= Node
;
195 pragma Assert
(Z
/= 0);
197 N
: Nodes_Type
renames Tree
.Nodes
;
200 if Tree
.Busy
> 0 then
201 raise Program_Error
with
202 "attempt to tamper with cursors (container is busy)";
205 pragma Assert
(Tree
.Length
> 0);
206 pragma Assert
(Tree
.Root
/= 0);
207 pragma Assert
(Tree
.First
/= 0);
208 pragma Assert
(Tree
.Last
/= 0);
209 pragma Assert
(Parent
(N
(Tree
.Root
)) = 0);
211 pragma Assert
((Tree
.Length
> 1)
212 or else (Tree
.First
= Tree
.Last
213 and then Tree
.First
= Tree
.Root
));
215 pragma Assert
((Left
(N
(Node
)) = 0)
216 or else (Parent
(N
(Left
(N
(Node
)))) = Node
));
218 pragma Assert
((Right
(N
(Node
)) = 0)
219 or else (Parent
(N
(Right
(N
(Node
)))) = Node
));
221 pragma Assert
(((Parent
(N
(Node
)) = 0) and then (Tree
.Root
= Node
))
222 or else ((Parent
(N
(Node
)) /= 0) and then
223 ((Left
(N
(Parent
(N
(Node
)))) = Node
)
225 (Right
(N
(Parent
(N
(Node
)))) = Node
))));
227 if Left
(N
(Z
)) = 0 then
228 if Right
(N
(Z
)) = 0 then
229 if Z
= Tree
.First
then
230 Tree
.First
:= Parent
(N
(Z
));
233 if Z
= Tree
.Last
then
234 Tree
.Last
:= Parent
(N
(Z
));
237 if Color
(N
(Z
)) = Black
then
238 Delete_Fixup
(Tree
, Z
);
241 pragma Assert
(Left
(N
(Z
)) = 0);
242 pragma Assert
(Right
(N
(Z
)) = 0);
244 if Z
= Tree
.Root
then
245 pragma Assert
(Tree
.Length
= 1);
246 pragma Assert
(Parent
(N
(Z
)) = 0);
248 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
249 Set_Left
(N
(Parent
(N
(Z
))), 0);
251 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
252 Set_Right
(N
(Parent
(N
(Z
))), 0);
256 pragma Assert
(Z
/= Tree
.Last
);
260 if Z
= Tree
.First
then
261 Tree
.First
:= Min
(Tree
, X
);
264 if Z
= Tree
.Root
then
266 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
267 Set_Left
(N
(Parent
(N
(Z
))), X
);
269 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
270 Set_Right
(N
(Parent
(N
(Z
))), X
);
273 Set_Parent
(N
(X
), Parent
(N
(Z
)));
275 if Color
(N
(Z
)) = Black
then
276 Delete_Fixup
(Tree
, X
);
280 elsif Right
(N
(Z
)) = 0 then
281 pragma Assert
(Z
/= Tree
.First
);
285 if Z
= Tree
.Last
then
286 Tree
.Last
:= Max
(Tree
, X
);
289 if Z
= Tree
.Root
then
291 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
292 Set_Left
(N
(Parent
(N
(Z
))), X
);
294 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
295 Set_Right
(N
(Parent
(N
(Z
))), X
);
298 Set_Parent
(N
(X
), Parent
(N
(Z
)));
300 if Color
(N
(Z
)) = Black
then
301 Delete_Fixup
(Tree
, X
);
305 pragma Assert
(Z
/= Tree
.First
);
306 pragma Assert
(Z
/= Tree
.Last
);
309 pragma Assert
(Left
(N
(Y
)) = 0);
314 if Y
= Left
(N
(Parent
(N
(Y
)))) then
315 pragma Assert
(Parent
(N
(Y
)) /= Z
);
316 Delete_Swap
(Tree
, Z
, Y
);
317 Set_Left
(N
(Parent
(N
(Z
))), Z
);
320 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
321 pragma Assert
(Parent
(N
(Y
)) = Z
);
322 Set_Parent
(N
(Y
), Parent
(N
(Z
)));
324 if Z
= Tree
.Root
then
326 elsif Z
= Left
(N
(Parent
(N
(Z
)))) then
327 Set_Left
(N
(Parent
(N
(Z
))), Y
);
329 pragma Assert
(Z
= Right
(N
(Parent
(N
(Z
)))));
330 Set_Right
(N
(Parent
(N
(Z
))), Y
);
334 Set_Parent
(N
(Left
(N
(Y
))), Y
);
335 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
530 -- the next link for a node on the free store is negative, then
531 -- this means the remaining nodes on the free store are
532 -- physically contiguous, starting as the absolute value of
535 Tree
.Free
:= abs Tree
.Free
;
537 if Tree
.Free
> Tree
.Capacity
then
541 for I
in Tree
.Free
.. Tree
.Capacity
- 1 loop
542 Set_Parent
(N
(I
), I
+ 1);
545 Set_Parent
(N
(Tree
.Capacity
), 0);
548 Set_Parent
(N
(X
), Tree
.Free
);
553 -----------------------
554 -- Generic_Allocate --
555 -----------------------
557 procedure Generic_Allocate
558 (Tree
: in out Tree_Type
'Class;
559 Node
: out Count_Type
)
561 N
: Nodes_Type
renames Tree
.Nodes
;
564 if Tree
.Free
>= 0 then
567 -- We always perform the assignment first, before we
568 -- change container state, in order to defend against
569 -- exceptions duration assignment.
571 Set_Element
(N
(Node
));
572 Tree
.Free
:= Parent
(N
(Node
));
575 -- A negative free store value means that the links of the nodes
576 -- in the free store have not been initialized. In this case, the
577 -- nodes are physically contiguous in the array, starting at the
578 -- index that is the absolute value of the Container.Free, and
579 -- continuing until the end of the array (Nodes'Last).
581 Node
:= abs Tree
.Free
;
583 -- As above, we perform this assignment first, before modifying
584 -- any container state.
586 Set_Element
(N
(Node
));
587 Tree
.Free
:= Tree
.Free
- 1;
589 end Generic_Allocate
;
595 function Generic_Equal
(Left
, Right
: Tree_Type
'Class) return Boolean is
600 if Left
'Address = Right
'Address then
604 if Left
.Length
/= Right
.Length
then
608 L_Node
:= Left
.First
;
609 R_Node
:= Right
.First
;
610 while L_Node
/= 0 loop
611 if not Is_Equal
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
615 L_Node
:= Next
(Left
, L_Node
);
616 R_Node
:= Next
(Right
, R_Node
);
622 -----------------------
623 -- Generic_Iteration --
624 -----------------------
626 procedure Generic_Iteration
(Tree
: Tree_Type
'Class) is
627 procedure Iterate
(P
: Count_Type
);
633 procedure Iterate
(P
: Count_Type
) is
637 Iterate
(Left
(Tree
.Nodes
(X
)));
639 X
:= Right
(Tree
.Nodes
(X
));
643 -- Start of processing for Generic_Iteration
647 end Generic_Iteration
;
653 procedure Generic_Read
654 (Stream
: not null access Root_Stream_Type
'Class;
655 Tree
: in out Tree_Type
'Class)
657 Len
: Count_Type
'Base;
659 Node
, Last_Node
: Count_Type
;
661 N
: Nodes_Type
renames Tree
.Nodes
;
665 Count_Type
'Base'Read (Stream, Len);
668 raise Program_Error with "bad container length (corrupt stream)";
675 if Len > Tree.Capacity then
676 raise Constraint_Error with "length exceeds capacity";
679 -- Use Unconditional_Insert_With_Hint here instead ???
681 Allocate (Tree, Node);
682 pragma Assert (Node /= 0);
684 Set_Color (N (Node), Black);
691 for J in Count_Type range 2 .. Len loop
693 pragma Assert (Last_Node = Tree.Last);
695 Allocate (Tree, Node);
696 pragma Assert (Node /= 0);
698 Set_Color (N (Node), Red);
699 Set_Right (N (Last_Node), Right => Node);
701 Set_Parent (N (Node), Parent => Last_Node);
703 Rebalance_For_Insert (Tree, Node);
704 Tree.Length := Tree.Length + 1;
708 -------------------------------
709 -- Generic_Reverse_Iteration --
710 -------------------------------
712 procedure Generic_Reverse_Iteration (Tree : Tree_Type'Class) is
713 procedure Iterate (P : Count_Type);
719 procedure Iterate (P : Count_Type) is
723 Iterate (Right (Tree.Nodes (X)));
725 X := Left (Tree.Nodes (X));
729 -- Start of processing for Generic_Reverse_Iteration
733 end Generic_Reverse_Iteration;
739 procedure Generic_Write
740 (Stream : not null access Root_Stream_Type'Class;
741 Tree : Tree_Type'Class)
743 procedure Process (Node : Count_Type);
744 pragma Inline (Process);
747 new Generic_Iteration (Process);
753 procedure Process (Node : Count_Type) is
755 Write_Node (Stream, Tree.Nodes (Node));
758 -- Start of processing for Generic_Write
761 Count_Type'Base'Write
(Stream
, Tree
.Length
);
769 procedure Left_Rotate
(Tree
: in out Tree_Type
'Class; X
: Count_Type
) is
772 N
: Nodes_Type
renames Tree
.Nodes
;
774 Y
: constant Count_Type
:= Right
(N
(X
));
775 pragma Assert
(Y
/= 0);
778 Set_Right
(N
(X
), Left
(N
(Y
)));
780 if Left
(N
(Y
)) /= 0 then
781 Set_Parent
(N
(Left
(N
(Y
))), X
);
784 Set_Parent
(N
(Y
), Parent
(N
(X
)));
786 if X
= Tree
.Root
then
788 elsif X
= Left
(N
(Parent
(N
(X
)))) then
789 Set_Left
(N
(Parent
(N
(X
))), Y
);
791 pragma Assert
(X
= Right
(N
(Parent
(N
(X
)))));
792 Set_Right
(N
(Parent
(N
(X
))), Y
);
796 Set_Parent
(N
(X
), Y
);
804 (Tree
: Tree_Type
'Class;
805 Node
: Count_Type
) return Count_Type
809 X
: Count_Type
:= Node
;
814 Y
:= Right
(Tree
.Nodes
(X
));
829 (Tree
: Tree_Type
'Class;
830 Node
: Count_Type
) return Count_Type
834 X
: Count_Type
:= Node
;
839 Y
:= Left
(Tree
.Nodes
(X
));
854 (Tree
: Tree_Type
'Class;
855 Node
: Count_Type
) return Count_Type
864 if Right
(Tree
.Nodes
(Node
)) /= 0 then
865 return Min
(Tree
, Right
(Tree
.Nodes
(Node
)));
869 X
: Count_Type
:= Node
;
870 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
874 and then X
= Right
(Tree
.Nodes
(Y
))
877 Y
:= Parent
(Tree
.Nodes
(Y
));
889 (Tree
: Tree_Type
'Class;
890 Node
: Count_Type
) return Count_Type
897 if Left
(Tree
.Nodes
(Node
)) /= 0 then
898 return Max
(Tree
, Left
(Tree
.Nodes
(Node
)));
902 X
: Count_Type
:= Node
;
903 Y
: Count_Type
:= Parent
(Tree
.Nodes
(Node
));
907 and then X
= Left
(Tree
.Nodes
(Y
))
910 Y
:= Parent
(Tree
.Nodes
(Y
));
917 --------------------------
918 -- Rebalance_For_Insert --
919 --------------------------
921 procedure Rebalance_For_Insert
922 (Tree
: in out Tree_Type
'Class;
927 N
: Nodes_Type
renames Tree
.Nodes
;
929 X
: Count_Type
:= Node
;
930 pragma Assert
(X
/= 0);
931 pragma Assert
(Color
(N
(X
)) = Red
);
936 while X
/= Tree
.Root
and then Color
(N
(Parent
(N
(X
)))) = Red
loop
937 if Parent
(N
(X
)) = Left
(N
(Parent
(N
(Parent
(N
(X
)))))) then
938 Y
:= Right
(N
(Parent
(N
(Parent
(N
(X
))))));
940 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
941 Set_Color
(N
(Parent
(N
(X
))), Black
);
942 Set_Color
(N
(Y
), Black
);
943 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
944 X
:= Parent
(N
(Parent
(N
(X
))));
947 if X
= Right
(N
(Parent
(N
(X
)))) then
949 Left_Rotate
(Tree
, X
);
952 Set_Color
(N
(Parent
(N
(X
))), Black
);
953 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
954 Right_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
958 pragma Assert
(Parent
(N
(X
)) =
959 Right
(N
(Parent
(N
(Parent
(N
(X
)))))));
961 Y
:= Left
(N
(Parent
(N
(Parent
(N
(X
))))));
963 if Y
/= 0 and then Color
(N
(Y
)) = Red
then
964 Set_Color
(N
(Parent
(N
(X
))), Black
);
965 Set_Color
(N
(Y
), Black
);
966 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
967 X
:= Parent
(N
(Parent
(N
(X
))));
970 if X
= Left
(N
(Parent
(N
(X
)))) then
972 Right_Rotate
(Tree
, X
);
975 Set_Color
(N
(Parent
(N
(X
))), Black
);
976 Set_Color
(N
(Parent
(N
(Parent
(N
(X
))))), Red
);
977 Left_Rotate
(Tree
, Parent
(N
(Parent
(N
(X
)))));
982 Set_Color
(N
(Tree
.Root
), Black
);
983 end Rebalance_For_Insert
;
989 procedure Right_Rotate
(Tree
: in out Tree_Type
'Class; Y
: Count_Type
) is
990 N
: Nodes_Type
renames Tree
.Nodes
;
992 X
: constant Count_Type
:= Left
(N
(Y
));
993 pragma Assert
(X
/= 0);
996 Set_Left
(N
(Y
), Right
(N
(X
)));
998 if Right
(N
(X
)) /= 0 then
999 Set_Parent
(N
(Right
(N
(X
))), Y
);
1002 Set_Parent
(N
(X
), Parent
(N
(Y
)));
1004 if Y
= Tree
.Root
then
1006 elsif Y
= Left
(N
(Parent
(N
(Y
)))) then
1007 Set_Left
(N
(Parent
(N
(Y
))), X
);
1009 pragma Assert
(Y
= Right
(N
(Parent
(N
(Y
)))));
1010 Set_Right
(N
(Parent
(N
(Y
))), X
);
1013 Set_Right
(N
(X
), Y
);
1014 Set_Parent
(N
(Y
), X
);
1021 function Vet
(Tree
: Tree_Type
'Class; Index
: Count_Type
) return Boolean is
1022 Nodes
: Nodes_Type
renames Tree
.Nodes
;
1023 Node
: Node_Type
renames Nodes
(Index
);
1026 if Parent
(Node
) = Index
1027 or else Left
(Node
) = Index
1028 or else Right
(Node
) = Index
1034 or else Tree
.Root
= 0
1035 or else Tree
.First
= 0
1036 or else Tree
.Last
= 0
1041 if Parent
(Nodes
(Tree
.Root
)) /= 0 then
1045 if Left
(Nodes
(Tree
.First
)) /= 0 then
1049 if Right
(Nodes
(Tree
.Last
)) /= 0 then
1053 if Tree
.Length
= 1 then
1054 if Tree
.First
/= Tree
.Last
1055 or else Tree
.First
/= Tree
.Root
1060 if Index
/= Tree
.First
then
1064 if Parent
(Node
) /= 0
1065 or else Left
(Node
) /= 0
1066 or else Right
(Node
) /= 0
1074 if Tree
.First
= Tree
.Last
then
1078 if Tree
.Length
= 2 then
1079 if Tree
.First
/= Tree
.Root
1080 and then Tree
.Last
/= Tree
.Root
1085 if Tree
.First
/= Index
1086 and then Tree
.Last
/= Index
1093 and then Parent
(Nodes
(Left
(Node
))) /= Index
1098 if Right
(Node
) /= 0
1099 and then Parent
(Nodes
(Right
(Node
))) /= Index
1104 if Parent
(Node
) = 0 then
1105 if Tree
.Root
/= Index
then
1109 elsif Left
(Nodes
(Parent
(Node
))) /= Index
1110 and then Right
(Nodes
(Parent
(Node
))) /= Index
1118 end Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
;