1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S . --
6 -- G E N E R I C _ O P E R A T I O N S --
10 -- Copyright (C) 2004-2006, Free Software Foundation, Inc. --
12 -- This specification is derived from the Ada Reference Manual for use with --
13 -- GNAT. The copyright notice above, and the license provisions that follow --
14 -- apply solely to the contents of the part following the private keyword. --
16 -- GNAT is free software; you can redistribute it and/or modify it under --
17 -- terms of the GNU General Public License as published by the Free Soft- --
18 -- ware Foundation; either version 2, or (at your option) any later ver- --
19 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
20 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
21 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
22 -- for more details. You should have received a copy of the GNU General --
23 -- Public License distributed with GNAT; see file COPYING. If not, write --
24 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
25 -- Boston, MA 02110-1301, USA. --
27 -- As a special exception, if other files instantiate generics from this --
28 -- unit, or you link this unit with other files to produce an executable, --
29 -- this unit does not by itself cause the resulting executable to be --
30 -- covered by the GNU General Public License. This exception does not --
31 -- however invalidate any other reasons why the executable file might be --
32 -- covered by the GNU Public License. --
34 -- This unit was originally developed by Matthew J Heaney. --
35 ------------------------------------------------------------------------------
37 with System; use type System.Address;
39 package body Ada.Containers.Red_Black_Trees.Generic_Operations is
41 -----------------------
42 -- Local Subprograms --
43 -----------------------
45 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access);
47 procedure Delete_Swap (Tree : in out Tree_Type; Z, Y : Node_Access);
49 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access);
50 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access);
52 -- ---------------------
53 -- -- Check_Invariant --
54 -- ---------------------
56 -- procedure Check_Invariant (Tree : Tree_Type) is
57 -- Root : constant Node_Access := Tree.Root;
59 -- function Check (Node : Node_Access) return Natural;
65 -- function Check (Node : Node_Access) return Natural is
67 -- if Node = null then
71 -- if Color (Node) = Red then
73 -- L : constant Node_Access := Left (Node);
75 -- pragma Assert (L = null or else Color (L) = Black);
80 -- R : constant Node_Access := Right (Node);
82 -- pragma Assert (R = null or else Color (R) = Black);
87 -- NL : constant Natural := Check (Left (Node));
88 -- NR : constant Natural := Check (Right (Node));
90 -- pragma Assert (NL = NR);
96 -- NL : constant Natural := Check (Left (Node));
97 -- NR : constant Natural := Check (Right (Node));
99 -- pragma Assert (NL = NR);
104 -- -- Start of processing for Check_Invariant
107 -- if Root = null then
108 -- pragma Assert (Tree.First = null);
109 -- pragma Assert (Tree.Last = null);
110 -- pragma Assert (Tree.Length = 0);
114 -- pragma Assert (Color (Root) = Black);
115 -- pragma Assert (Tree.Length > 0);
116 -- pragma Assert (Tree.Root /= null);
117 -- pragma Assert (Tree.First /= null);
118 -- pragma Assert (Tree.Last /= null);
119 -- pragma Assert (Parent (Tree.Root) = null);
120 -- pragma Assert ((Tree.Length > 1)
121 -- or else (Tree.First = Tree.Last
122 -- and Tree.First = Tree.Root));
123 -- pragma Assert (Left (Tree.First) = null);
124 -- pragma Assert (Right (Tree.Last) = null);
127 -- L : constant Node_Access := Left (Root);
128 -- R : constant Node_Access := Right (Root);
129 -- NL : constant Natural := Check (L);
130 -- NR : constant Natural := Check (R);
132 -- pragma Assert (NL = NR);
136 -- end Check_Invariant;
142 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access) is
146 X : Node_Access := Node;
151 and then Color (X) = Black
153 if X = Left (Parent (X)) then
154 W := Right (Parent (X));
156 if Color (W) = Red then
157 Set_Color (W, Black);
158 Set_Color (Parent (X), Red);
159 Left_Rotate (Tree, Parent (X));
160 W := Right (Parent (X));
163 if (Left (W) = null or else Color (Left (W)) = Black)
165 (Right (W) = null or else Color (Right (W)) = Black)
172 or else Color (Right (W)) = Black
174 if Left (W) /= null then
175 Set_Color (Left (W), Black);
179 Right_Rotate (Tree, W);
180 W := Right (Parent (X));
183 Set_Color (W, Color (Parent (X)));
184 Set_Color (Parent (X), Black);
185 Set_Color (Right (W), Black);
186 Left_Rotate (Tree, Parent (X));
191 pragma Assert (X = Right (Parent (X)));
193 W := Left (Parent (X));
195 if Color (W) = Red then
196 Set_Color (W, Black);
197 Set_Color (Parent (X), Red);
198 Right_Rotate (Tree, Parent (X));
199 W := Left (Parent (X));
202 if (Left (W) = null or else Color (Left (W)) = Black)
204 (Right (W) = null or else Color (Right (W)) = Black)
210 if Left (W) = null or else Color (Left (W)) = Black then
211 if Right (W) /= null then
212 Set_Color (Right (W), Black);
216 Left_Rotate (Tree, W);
217 W := Left (Parent (X));
220 Set_Color (W, Color (Parent (X)));
221 Set_Color (Parent (X), Black);
222 Set_Color (Left (W), Black);
223 Right_Rotate (Tree, Parent (X));
229 Set_Color (X, Black);
232 ---------------------------
233 -- Delete_Node_Sans_Free --
234 ---------------------------
236 procedure Delete_Node_Sans_Free
237 (Tree : in out Tree_Type;
244 Z : constant Node_Access := Node;
245 pragma Assert (Z /= null);
248 if Tree.Busy > 0 then
249 raise Program_Error with
250 "attempt to tamper with cursors (container is busy)";
253 -- pragma Assert (Tree.Length > 0);
254 -- pragma Assert (Tree.Root /= null);
255 -- pragma Assert (Tree.First /= null);
256 -- pragma Assert (Tree.Last /= null);
257 -- pragma Assert (Parent (Tree.Root) = null);
258 -- pragma Assert ((Tree.Length > 1)
259 -- or else (Tree.First = Tree.Last
260 -- and then Tree.First = Tree.Root));
261 -- pragma Assert ((Left (Node) = null)
262 -- or else (Parent (Left (Node)) = Node));
263 -- pragma Assert ((Right (Node) = null)
264 -- or else (Parent (Right (Node)) = Node));
265 -- pragma Assert (((Parent (Node) = null) and then (Tree.Root = Node))
266 -- or else ((Parent (Node) /= null) and then
267 -- ((Left (Parent (Node)) = Node)
268 -- or else (Right (Parent (Node)) = Node))));
270 if Left (Z) = null then
271 if Right (Z) = null then
272 if Z = Tree.First then
273 Tree.First := Parent (Z);
276 if Z = Tree.Last then
277 Tree.Last := Parent (Z);
280 if Color (Z) = Black then
281 Delete_Fixup (Tree, Z);
284 pragma Assert (Left (Z) = null);
285 pragma Assert (Right (Z) = null);
287 if Z = Tree.Root then
288 pragma Assert (Tree.Length = 1);
289 pragma Assert (Parent (Z) = null);
291 elsif Z = Left (Parent (Z)) then
292 Set_Left (Parent (Z), null);
294 pragma Assert (Z = Right (Parent (Z)));
295 Set_Right (Parent (Z), null);
299 pragma Assert (Z /= Tree.Last);
303 if Z = Tree.First then
304 Tree.First := Min (X);
307 if Z = Tree.Root then
309 elsif Z = Left (Parent (Z)) then
310 Set_Left (Parent (Z), X);
312 pragma Assert (Z = Right (Parent (Z)));
313 Set_Right (Parent (Z), X);
316 Set_Parent (X, Parent (Z));
318 if Color (Z) = Black then
319 Delete_Fixup (Tree, X);
323 elsif Right (Z) = null then
324 pragma Assert (Z /= Tree.First);
328 if Z = Tree.Last then
329 Tree.Last := Max (X);
332 if Z = Tree.Root then
334 elsif Z = Left (Parent (Z)) then
335 Set_Left (Parent (Z), X);
337 pragma Assert (Z = Right (Parent (Z)));
338 Set_Right (Parent (Z), X);
341 Set_Parent (X, Parent (Z));
343 if Color (Z) = Black then
344 Delete_Fixup (Tree, X);
348 pragma Assert (Z /= Tree.First);
349 pragma Assert (Z /= Tree.Last);
352 pragma Assert (Left (Y) = null);
357 if Y = Left (Parent (Y)) then
358 pragma Assert (Parent (Y) /= Z);
359 Delete_Swap (Tree, Z, Y);
360 Set_Left (Parent (Z), Z);
363 pragma Assert (Y = Right (Parent (Y)));
364 pragma Assert (Parent (Y) = Z);
365 Set_Parent (Y, Parent (Z));
367 if Z = Tree.Root then
369 elsif Z = Left (Parent (Z)) then
370 Set_Left (Parent (Z), Y);
372 pragma Assert (Z = Right (Parent (Z)));
373 Set_Right (Parent (Z), Y);
376 Set_Left (Y, Left (Z));
377 Set_Parent (Left (Y), Y);
384 Y_Color : constant Color_Type := Color (Y);
386 Set_Color (Y, Color (Z));
387 Set_Color (Z, Y_Color);
391 if Color (Z) = Black then
392 Delete_Fixup (Tree, Z);
395 pragma Assert (Left (Z) = null);
396 pragma Assert (Right (Z) = null);
398 if Z = Right (Parent (Z)) then
399 Set_Right (Parent (Z), null);
401 pragma Assert (Z = Left (Parent (Z)));
402 Set_Left (Parent (Z), null);
406 if Y = Left (Parent (Y)) then
407 pragma Assert (Parent (Y) /= Z);
409 Delete_Swap (Tree, Z, Y);
411 Set_Left (Parent (Z), X);
412 Set_Parent (X, Parent (Z));
415 pragma Assert (Y = Right (Parent (Y)));
416 pragma Assert (Parent (Y) = Z);
418 Set_Parent (Y, Parent (Z));
420 if Z = Tree.Root then
422 elsif Z = Left (Parent (Z)) then
423 Set_Left (Parent (Z), Y);
425 pragma Assert (Z = Right (Parent (Z)));
426 Set_Right (Parent (Z), Y);
429 Set_Left (Y, Left (Z));
430 Set_Parent (Left (Y), Y);
433 Y_Color : constant Color_Type := Color (Y);
435 Set_Color (Y, Color (Z));
436 Set_Color (Z, Y_Color);
440 if Color (Z) = Black then
441 Delete_Fixup (Tree, X);
446 Tree.Length := Tree.Length - 1;
447 end Delete_Node_Sans_Free;
453 procedure Delete_Swap
454 (Tree : in out Tree_Type;
457 pragma Assert (Z /= Y);
458 pragma Assert (Parent (Y) /= Z);
460 Y_Parent : constant Node_Access := Parent (Y);
461 Y_Color : constant Color_Type := Color (Y);
464 Set_Parent (Y, Parent (Z));
465 Set_Left (Y, Left (Z));
466 Set_Right (Y, Right (Z));
467 Set_Color (Y, Color (Z));
469 if Tree.Root = Z then
471 elsif Right (Parent (Y)) = Z then
472 Set_Right (Parent (Y), Y);
474 pragma Assert (Left (Parent (Y)) = Z);
475 Set_Left (Parent (Y), Y);
478 if Right (Y) /= null then
479 Set_Parent (Right (Y), Y);
482 if Left (Y) /= null then
483 Set_Parent (Left (Y), Y);
486 Set_Parent (Z, Y_Parent);
487 Set_Color (Z, Y_Color);
496 procedure Generic_Adjust (Tree : in out Tree_Type) is
497 N : constant Count_Type := Tree.Length;
498 Root : constant Node_Access := Tree.Root;
502 pragma Assert (Root = null);
503 pragma Assert (Tree.Busy = 0);
504 pragma Assert (Tree.Lock = 0);
513 Tree.Root := Copy_Tree (Root);
514 Tree.First := Min (Tree.Root);
515 Tree.Last := Max (Tree.Root);
523 procedure Generic_Clear (Tree : in out Tree_Type) is
524 Root : Node_Access := Tree.Root;
526 if Tree.Busy > 0 then
527 raise Program_Error with
528 "attempt to tamper with cursors (container is busy)";
531 Tree := (First => null,
541 -----------------------
542 -- Generic_Copy_Tree --
543 -----------------------
545 function Generic_Copy_Tree (Source_Root : Node_Access) return Node_Access is
546 Target_Root : Node_Access := Copy_Node (Source_Root);
550 if Right (Source_Root) /= null then
552 (Node => Target_Root,
553 Right => Generic_Copy_Tree (Right (Source_Root)));
556 (Node => Right (Target_Root),
557 Parent => Target_Root);
562 X := Left (Source_Root);
565 Y : constant Node_Access := Copy_Node (X);
567 Set_Left (Node => P, Left => Y);
568 Set_Parent (Node => Y, Parent => P);
570 if Right (X) /= null then
573 Right => Generic_Copy_Tree (Right (X)));
588 Delete_Tree (Target_Root);
590 end Generic_Copy_Tree;
592 -------------------------
593 -- Generic_Delete_Tree --
594 -------------------------
596 procedure Generic_Delete_Tree (X : in out Node_Access) is
601 Generic_Delete_Tree (Y);
606 end Generic_Delete_Tree;
612 function Generic_Equal (Left, Right : Tree_Type) return Boolean is
613 L_Node : Node_Access;
614 R_Node : Node_Access;
617 if Left'Address = Right'Address then
621 if Left.Length /= Right.Length then
625 L_Node := Left.First;
626 R_Node := Right.First;
627 while L_Node /= null loop
628 if not Is_Equal (L_Node, R_Node) then
632 L_Node := Next (L_Node);
633 R_Node := Next (R_Node);
639 -----------------------
640 -- Generic_Iteration --
641 -----------------------
643 procedure Generic_Iteration (Tree : Tree_Type) is
644 procedure Iterate (P : Node_Access);
650 procedure Iterate (P : Node_Access) is
651 X : Node_Access := P;
660 -- Start of processing for Generic_Iteration
664 end Generic_Iteration;
670 procedure Generic_Move (Target, Source : in out Tree_Type) is
672 if Target'Address = Source'Address then
676 if Source.Busy > 0 then
677 raise Program_Error with
678 "attempt to tamper with cursors (container is busy)";
685 Source := (First => null,
697 procedure Generic_Read
698 (Stream : access Root_Stream_Type'Class;
699 Tree : in out Tree_Type)
703 Node, Last_Node : Node_Access;
708 Count_Type'Base'Read (Stream, N);
709 pragma Assert (N >= 0);
715 Node := Read_Node (Stream);
716 pragma Assert (Node /= null);
717 pragma Assert (Color (Node) = Red);
719 Set_Color (Node, Black);
727 for J in Count_Type range 2 .. N loop
729 pragma Assert (Last_Node = Tree.Last);
731 Node := Read_Node (Stream);
732 pragma Assert (Node /= null);
733 pragma Assert (Color (Node) = Red);
735 Set_Right (Node => Last_Node, Right => Node);
737 Set_Parent (Node => Node, Parent => Last_Node);
738 Rebalance_For_Insert (Tree, Node);
739 Tree.Length := Tree.Length + 1;
743 -------------------------------
744 -- Generic_Reverse_Iteration --
745 -------------------------------
747 procedure Generic_Reverse_Iteration (Tree : Tree_Type)
749 procedure Iterate (P : Node_Access);
755 procedure Iterate (P : Node_Access) is
756 X : Node_Access := P;
765 -- Start of processing for Generic_Reverse_Iteration
769 end Generic_Reverse_Iteration;
775 procedure Generic_Write
776 (Stream : access Root_Stream_Type'Class;
779 procedure Process (Node : Node_Access);
780 pragma Inline (Process);
783 new Generic_Iteration (Process);
789 procedure Process (Node : Node_Access) is
791 Write_Node (Stream, Node);
794 -- Start of processing for Generic_Write
797 Count_Type'Base'Write (Stream, Tree.Length);
805 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access) is
809 Y : constant Node_Access := Right (X);
810 pragma Assert (Y /= null);
813 Set_Right (X, Left (Y));
815 if Left (Y) /= null then
816 Set_Parent (Left (Y), X);
819 Set_Parent (Y, Parent (X));
821 if X = Tree.Root then
823 elsif X = Left (Parent (X)) then
824 Set_Left (Parent (X), Y);
826 pragma Assert (X = Right (Parent (X)));
827 Set_Right (Parent (X), Y);
838 function Max (Node : Node_Access) return Node_Access is
842 X : Node_Access := Node;
861 function Min (Node : Node_Access) return Node_Access is
865 X : Node_Access := Node;
884 function Next (Node : Node_Access) return Node_Access is
892 if Right (Node) /= null then
893 return Min (Right (Node));
897 X : Node_Access := Node;
898 Y : Node_Access := Parent (Node);
902 and then X = Right (Y)
908 -- Why is this code commented out ???
910 -- if Right (X) /= Y then
924 function Previous (Node : Node_Access) return Node_Access is
930 if Left (Node) /= null then
931 return Max (Left (Node));
935 X : Node_Access := Node;
936 Y : Node_Access := Parent (Node);
940 and then X = Left (Y)
946 -- Why is this code commented out ???
948 -- if Left (X) /= Y then
958 --------------------------
959 -- Rebalance_For_Insert --
960 --------------------------
962 procedure Rebalance_For_Insert
963 (Tree : in out Tree_Type;
968 X : Node_Access := Node;
969 pragma Assert (X /= null);
970 pragma Assert (Color (X) = Red);
975 while X /= Tree.Root and then Color (Parent (X)) = Red loop
976 if Parent (X) = Left (Parent (Parent (X))) then
977 Y := Right (Parent (Parent (X)));
979 if Y /= null and then Color (Y) = Red then
980 Set_Color (Parent (X), Black);
981 Set_Color (Y, Black);
982 Set_Color (Parent (Parent (X)), Red);
983 X := Parent (Parent (X));
986 if X = Right (Parent (X)) then
988 Left_Rotate (Tree, X);
991 Set_Color (Parent (X), Black);
992 Set_Color (Parent (Parent (X)), Red);
993 Right_Rotate (Tree, Parent (Parent (X)));
997 pragma Assert (Parent (X) = Right (Parent (Parent (X))));
999 Y := Left (Parent (Parent (X)));
1001 if Y /= null and then Color (Y) = Red then
1002 Set_Color (Parent (X), Black);
1003 Set_Color (Y, Black);
1004 Set_Color (Parent (Parent (X)), Red);
1005 X := Parent (Parent (X));
1008 if X = Left (Parent (X)) then
1010 Right_Rotate (Tree, X);
1013 Set_Color (Parent (X), Black);
1014 Set_Color (Parent (Parent (X)), Red);
1015 Left_Rotate (Tree, Parent (Parent (X)));
1020 Set_Color (Tree.Root, Black);
1021 end Rebalance_For_Insert;
1027 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access) is
1028 X : constant Node_Access := Left (Y);
1029 pragma Assert (X /= null);
1032 Set_Left (Y, Right (X));
1034 if Right (X) /= null then
1035 Set_Parent (Right (X), Y);
1038 Set_Parent (X, Parent (Y));
1040 if Y = Tree.Root then
1042 elsif Y = Left (Parent (Y)) then
1043 Set_Left (Parent (Y), X);
1045 pragma Assert (Y = Right (Parent (Y)));
1046 Set_Right (Parent (Y), X);
1057 function Vet (Tree : Tree_Type; Node : Node_Access) return Boolean is
1063 if Parent (Node) = Node
1064 or else Left (Node) = Node
1065 or else Right (Node) = Node
1071 or else Tree.Root = null
1072 or else Tree.First = null
1073 or else Tree.Last = null
1078 if Parent (Tree.Root) /= null then
1082 if Left (Tree.First) /= null then
1086 if Right (Tree.Last) /= null then
1090 if Tree.Length = 1 then
1091 if Tree.First /= Tree.Last
1092 or else Tree.First /= Tree.Root
1097 if Node /= Tree.First then
1101 if Parent (Node) /= null
1102 or else Left (Node) /= null
1103 or else Right (Node) /= null
1111 if Tree.First = Tree.Last then
1115 if Tree.Length = 2 then
1116 if Tree.First /= Tree.Root
1117 and then Tree.Last /= Tree.Root
1122 if Tree.First /= Node
1123 and then Tree.Last /= Node
1129 if Left (Node) /= null
1130 and then Parent (Left (Node)) /= Node
1135 if Right (Node) /= null
1136 and then Parent (Right (Node)) /= Node
1141 if Parent (Node) = null then
1142 if Tree.Root /= Node then
1146 elsif Left (Parent (Node)) /= Node
1147 and then Right (Parent (Node)) /= Node
1155 end Ada.Containers.Red_Black_Trees.Generic_Operations;