1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_OPERATIONS --
9 -- Copyright (C) 2004-2007, 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- This unit was originally developed by Matthew J Heaney. --
30 ------------------------------------------------------------------------------
32 -- The references below to "CLR" refer to the following book, from which
33 -- several of the algorithms here were adapted:
34 -- Introduction to Algorithms
35 -- by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest
36 -- Publisher: The MIT Press (June 18, 1990)
39 with System; use type System.Address;
41 package body Ada.Containers.Red_Black_Trees.Generic_Operations is
43 -----------------------
44 -- Local Subprograms --
45 -----------------------
47 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access);
49 procedure Delete_Swap (Tree : in out Tree_Type; Z, Y : Node_Access);
51 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access);
52 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access);
54 -- ---------------------
55 -- -- Check_Invariant --
56 -- ---------------------
58 -- procedure Check_Invariant (Tree : Tree_Type) is
59 -- Root : constant Node_Access := Tree.Root;
61 -- function Check (Node : Node_Access) return Natural;
67 -- function Check (Node : Node_Access) return Natural is
69 -- if Node = null then
73 -- if Color (Node) = Red then
75 -- L : constant Node_Access := Left (Node);
77 -- pragma Assert (L = null or else Color (L) = Black);
82 -- R : constant Node_Access := Right (Node);
84 -- pragma Assert (R = null or else Color (R) = Black);
89 -- NL : constant Natural := Check (Left (Node));
90 -- NR : constant Natural := Check (Right (Node));
92 -- pragma Assert (NL = NR);
98 -- NL : constant Natural := Check (Left (Node));
99 -- NR : constant Natural := Check (Right (Node));
101 -- pragma Assert (NL = NR);
106 -- -- Start of processing for Check_Invariant
109 -- if Root = null then
110 -- pragma Assert (Tree.First = null);
111 -- pragma Assert (Tree.Last = null);
112 -- pragma Assert (Tree.Length = 0);
116 -- pragma Assert (Color (Root) = Black);
117 -- pragma Assert (Tree.Length > 0);
118 -- pragma Assert (Tree.Root /= null);
119 -- pragma Assert (Tree.First /= null);
120 -- pragma Assert (Tree.Last /= null);
121 -- pragma Assert (Parent (Tree.Root) = null);
122 -- pragma Assert ((Tree.Length > 1)
123 -- or else (Tree.First = Tree.Last
124 -- and Tree.First = Tree.Root));
125 -- pragma Assert (Left (Tree.First) = null);
126 -- pragma Assert (Right (Tree.Last) = null);
129 -- L : constant Node_Access := Left (Root);
130 -- R : constant Node_Access := Right (Root);
131 -- NL : constant Natural := Check (L);
132 -- NR : constant Natural := Check (R);
134 -- pragma Assert (NL = NR);
138 -- end Check_Invariant;
144 procedure Delete_Fixup (Tree : in out Tree_Type; Node : Node_Access) is
148 X : Node_Access := Node;
153 and then Color (X) = Black
155 if X = Left (Parent (X)) then
156 W := Right (Parent (X));
158 if Color (W) = Red then
159 Set_Color (W, Black);
160 Set_Color (Parent (X), Red);
161 Left_Rotate (Tree, Parent (X));
162 W := Right (Parent (X));
165 if (Left (W) = null or else Color (Left (W)) = Black)
167 (Right (W) = null or else Color (Right (W)) = Black)
174 or else Color (Right (W)) = Black
176 if Left (W) /= null then
177 Set_Color (Left (W), Black);
181 Right_Rotate (Tree, W);
182 W := Right (Parent (X));
185 Set_Color (W, Color (Parent (X)));
186 Set_Color (Parent (X), Black);
187 Set_Color (Right (W), Black);
188 Left_Rotate (Tree, Parent (X));
193 pragma Assert (X = Right (Parent (X)));
195 W := Left (Parent (X));
197 if Color (W) = Red then
198 Set_Color (W, Black);
199 Set_Color (Parent (X), Red);
200 Right_Rotate (Tree, Parent (X));
201 W := Left (Parent (X));
204 if (Left (W) = null or else Color (Left (W)) = Black)
206 (Right (W) = null or else Color (Right (W)) = Black)
212 if Left (W) = null or else Color (Left (W)) = Black then
213 if Right (W) /= null then
214 Set_Color (Right (W), Black);
218 Left_Rotate (Tree, W);
219 W := Left (Parent (X));
222 Set_Color (W, Color (Parent (X)));
223 Set_Color (Parent (X), Black);
224 Set_Color (Left (W), Black);
225 Right_Rotate (Tree, Parent (X));
231 Set_Color (X, Black);
234 ---------------------------
235 -- Delete_Node_Sans_Free --
236 ---------------------------
238 procedure Delete_Node_Sans_Free
239 (Tree : in out Tree_Type;
246 Z : constant Node_Access := Node;
247 pragma Assert (Z /= null);
250 if Tree.Busy > 0 then
251 raise Program_Error with
252 "attempt to tamper with cursors (container is busy)";
255 -- pragma Assert (Tree.Length > 0);
256 -- pragma Assert (Tree.Root /= null);
257 -- pragma Assert (Tree.First /= null);
258 -- pragma Assert (Tree.Last /= null);
259 -- pragma Assert (Parent (Tree.Root) = null);
260 -- pragma Assert ((Tree.Length > 1)
261 -- or else (Tree.First = Tree.Last
262 -- and then Tree.First = Tree.Root));
263 -- pragma Assert ((Left (Node) = null)
264 -- or else (Parent (Left (Node)) = Node));
265 -- pragma Assert ((Right (Node) = null)
266 -- or else (Parent (Right (Node)) = Node));
267 -- pragma Assert (((Parent (Node) = null) and then (Tree.Root = Node))
268 -- or else ((Parent (Node) /= null) and then
269 -- ((Left (Parent (Node)) = Node)
270 -- or else (Right (Parent (Node)) = Node))));
272 if Left (Z) = null then
273 if Right (Z) = null then
274 if Z = Tree.First then
275 Tree.First := Parent (Z);
278 if Z = Tree.Last then
279 Tree.Last := Parent (Z);
282 if Color (Z) = Black then
283 Delete_Fixup (Tree, Z);
286 pragma Assert (Left (Z) = null);
287 pragma Assert (Right (Z) = null);
289 if Z = Tree.Root then
290 pragma Assert (Tree.Length = 1);
291 pragma Assert (Parent (Z) = null);
293 elsif Z = Left (Parent (Z)) then
294 Set_Left (Parent (Z), null);
296 pragma Assert (Z = Right (Parent (Z)));
297 Set_Right (Parent (Z), null);
301 pragma Assert (Z /= Tree.Last);
305 if Z = Tree.First then
306 Tree.First := Min (X);
309 if Z = Tree.Root then
311 elsif Z = Left (Parent (Z)) then
312 Set_Left (Parent (Z), X);
314 pragma Assert (Z = Right (Parent (Z)));
315 Set_Right (Parent (Z), X);
318 Set_Parent (X, Parent (Z));
320 if Color (Z) = Black then
321 Delete_Fixup (Tree, X);
325 elsif Right (Z) = null then
326 pragma Assert (Z /= Tree.First);
330 if Z = Tree.Last then
331 Tree.Last := Max (X);
334 if Z = Tree.Root then
336 elsif Z = Left (Parent (Z)) then
337 Set_Left (Parent (Z), X);
339 pragma Assert (Z = Right (Parent (Z)));
340 Set_Right (Parent (Z), X);
343 Set_Parent (X, Parent (Z));
345 if Color (Z) = Black then
346 Delete_Fixup (Tree, X);
350 pragma Assert (Z /= Tree.First);
351 pragma Assert (Z /= Tree.Last);
354 pragma Assert (Left (Y) = null);
359 if Y = Left (Parent (Y)) then
360 pragma Assert (Parent (Y) /= Z);
361 Delete_Swap (Tree, Z, Y);
362 Set_Left (Parent (Z), Z);
365 pragma Assert (Y = Right (Parent (Y)));
366 pragma Assert (Parent (Y) = Z);
367 Set_Parent (Y, Parent (Z));
369 if Z = Tree.Root then
371 elsif Z = Left (Parent (Z)) then
372 Set_Left (Parent (Z), Y);
374 pragma Assert (Z = Right (Parent (Z)));
375 Set_Right (Parent (Z), Y);
378 Set_Left (Y, Left (Z));
379 Set_Parent (Left (Y), Y);
386 Y_Color : constant Color_Type := Color (Y);
388 Set_Color (Y, Color (Z));
389 Set_Color (Z, Y_Color);
393 if Color (Z) = Black then
394 Delete_Fixup (Tree, Z);
397 pragma Assert (Left (Z) = null);
398 pragma Assert (Right (Z) = null);
400 if Z = Right (Parent (Z)) then
401 Set_Right (Parent (Z), null);
403 pragma Assert (Z = Left (Parent (Z)));
404 Set_Left (Parent (Z), null);
408 if Y = Left (Parent (Y)) then
409 pragma Assert (Parent (Y) /= Z);
411 Delete_Swap (Tree, Z, Y);
413 Set_Left (Parent (Z), X);
414 Set_Parent (X, Parent (Z));
417 pragma Assert (Y = Right (Parent (Y)));
418 pragma Assert (Parent (Y) = Z);
420 Set_Parent (Y, Parent (Z));
422 if Z = Tree.Root then
424 elsif Z = Left (Parent (Z)) then
425 Set_Left (Parent (Z), Y);
427 pragma Assert (Z = Right (Parent (Z)));
428 Set_Right (Parent (Z), Y);
431 Set_Left (Y, Left (Z));
432 Set_Parent (Left (Y), Y);
435 Y_Color : constant Color_Type := Color (Y);
437 Set_Color (Y, Color (Z));
438 Set_Color (Z, Y_Color);
442 if Color (Z) = Black then
443 Delete_Fixup (Tree, X);
448 Tree.Length := Tree.Length - 1;
449 end Delete_Node_Sans_Free;
455 procedure Delete_Swap
456 (Tree : in out Tree_Type;
459 pragma Assert (Z /= Y);
460 pragma Assert (Parent (Y) /= Z);
462 Y_Parent : constant Node_Access := Parent (Y);
463 Y_Color : constant Color_Type := Color (Y);
466 Set_Parent (Y, Parent (Z));
467 Set_Left (Y, Left (Z));
468 Set_Right (Y, Right (Z));
469 Set_Color (Y, Color (Z));
471 if Tree.Root = Z then
473 elsif Right (Parent (Y)) = Z then
474 Set_Right (Parent (Y), Y);
476 pragma Assert (Left (Parent (Y)) = Z);
477 Set_Left (Parent (Y), Y);
480 if Right (Y) /= null then
481 Set_Parent (Right (Y), Y);
484 if Left (Y) /= null then
485 Set_Parent (Left (Y), Y);
488 Set_Parent (Z, Y_Parent);
489 Set_Color (Z, Y_Color);
498 procedure Generic_Adjust (Tree : in out Tree_Type) is
499 N : constant Count_Type := Tree.Length;
500 Root : constant Node_Access := Tree.Root;
504 pragma Assert (Root = null);
505 pragma Assert (Tree.Busy = 0);
506 pragma Assert (Tree.Lock = 0);
515 Tree.Root := Copy_Tree (Root);
516 Tree.First := Min (Tree.Root);
517 Tree.Last := Max (Tree.Root);
525 procedure Generic_Clear (Tree : in out Tree_Type) is
526 Root : Node_Access := Tree.Root;
528 if Tree.Busy > 0 then
529 raise Program_Error with
530 "attempt to tamper with cursors (container is busy)";
533 Tree := (First => null,
543 -----------------------
544 -- Generic_Copy_Tree --
545 -----------------------
547 function Generic_Copy_Tree (Source_Root : Node_Access) return Node_Access is
548 Target_Root : Node_Access := Copy_Node (Source_Root);
552 if Right (Source_Root) /= null then
554 (Node => Target_Root,
555 Right => Generic_Copy_Tree (Right (Source_Root)));
558 (Node => Right (Target_Root),
559 Parent => Target_Root);
564 X := Left (Source_Root);
567 Y : constant Node_Access := Copy_Node (X);
569 Set_Left (Node => P, Left => Y);
570 Set_Parent (Node => Y, Parent => P);
572 if Right (X) /= null then
575 Right => Generic_Copy_Tree (Right (X)));
590 Delete_Tree (Target_Root);
592 end Generic_Copy_Tree;
594 -------------------------
595 -- Generic_Delete_Tree --
596 -------------------------
598 procedure Generic_Delete_Tree (X : in out Node_Access) is
600 pragma Warnings (Off, Y);
604 Generic_Delete_Tree (Y);
609 end Generic_Delete_Tree;
615 function Generic_Equal (Left, Right : Tree_Type) return Boolean is
616 L_Node : Node_Access;
617 R_Node : Node_Access;
620 if Left'Address = Right'Address then
624 if Left.Length /= Right.Length then
628 L_Node := Left.First;
629 R_Node := Right.First;
630 while L_Node /= null loop
631 if not Is_Equal (L_Node, R_Node) then
635 L_Node := Next (L_Node);
636 R_Node := Next (R_Node);
642 -----------------------
643 -- Generic_Iteration --
644 -----------------------
646 procedure Generic_Iteration (Tree : Tree_Type) is
647 procedure Iterate (P : Node_Access);
653 procedure Iterate (P : Node_Access) is
654 X : Node_Access := P;
663 -- Start of processing for Generic_Iteration
667 end Generic_Iteration;
673 procedure Generic_Move (Target, Source : in out Tree_Type) is
675 if Target'Address = Source'Address then
679 if Source.Busy > 0 then
680 raise Program_Error with
681 "attempt to tamper with cursors (container is busy)";
688 Source := (First => null,
700 procedure Generic_Read
701 (Stream : not null access Root_Stream_Type'Class;
702 Tree : in out Tree_Type)
706 Node, Last_Node : Node_Access;
711 Count_Type'Base'Read (Stream, N);
712 pragma Assert (N >= 0);
718 Node := Read_Node (Stream);
719 pragma Assert (Node /= null);
720 pragma Assert (Color (Node) = Red);
722 Set_Color (Node, Black);
730 for J in Count_Type range 2 .. N loop
732 pragma Assert (Last_Node = Tree.Last);
734 Node := Read_Node (Stream);
735 pragma Assert (Node /= null);
736 pragma Assert (Color (Node) = Red);
738 Set_Right (Node => Last_Node, Right => Node);
740 Set_Parent (Node => Node, Parent => Last_Node);
741 Rebalance_For_Insert (Tree, Node);
742 Tree.Length := Tree.Length + 1;
746 -------------------------------
747 -- Generic_Reverse_Iteration --
748 -------------------------------
750 procedure Generic_Reverse_Iteration (Tree : Tree_Type)
752 procedure Iterate (P : Node_Access);
758 procedure Iterate (P : Node_Access) is
759 X : Node_Access := P;
768 -- Start of processing for Generic_Reverse_Iteration
772 end Generic_Reverse_Iteration;
778 procedure Generic_Write
779 (Stream : not null access Root_Stream_Type'Class;
782 procedure Process (Node : Node_Access);
783 pragma Inline (Process);
786 new Generic_Iteration (Process);
792 procedure Process (Node : Node_Access) is
794 Write_Node (Stream, Node);
797 -- Start of processing for Generic_Write
800 Count_Type'Base'Write (Stream, Tree.Length);
808 procedure Left_Rotate (Tree : in out Tree_Type; X : Node_Access) is
812 Y : constant Node_Access := Right (X);
813 pragma Assert (Y /= null);
816 Set_Right (X, Left (Y));
818 if Left (Y) /= null then
819 Set_Parent (Left (Y), X);
822 Set_Parent (Y, Parent (X));
824 if X = Tree.Root then
826 elsif X = Left (Parent (X)) then
827 Set_Left (Parent (X), Y);
829 pragma Assert (X = Right (Parent (X)));
830 Set_Right (Parent (X), Y);
841 function Max (Node : Node_Access) return Node_Access is
845 X : Node_Access := Node;
864 function Min (Node : Node_Access) return Node_Access is
868 X : Node_Access := Node;
887 function Next (Node : Node_Access) return Node_Access is
895 if Right (Node) /= null then
896 return Min (Right (Node));
900 X : Node_Access := Node;
901 Y : Node_Access := Parent (Node);
905 and then X = Right (Y)
919 function Previous (Node : Node_Access) return Node_Access is
925 if Left (Node) /= null then
926 return Max (Left (Node));
930 X : Node_Access := Node;
931 Y : Node_Access := Parent (Node);
935 and then X = Left (Y)
945 --------------------------
946 -- Rebalance_For_Insert --
947 --------------------------
949 procedure Rebalance_For_Insert
950 (Tree : in out Tree_Type;
955 X : Node_Access := Node;
956 pragma Assert (X /= null);
957 pragma Assert (Color (X) = Red);
962 while X /= Tree.Root and then Color (Parent (X)) = Red loop
963 if Parent (X) = Left (Parent (Parent (X))) then
964 Y := Right (Parent (Parent (X)));
966 if Y /= null and then Color (Y) = Red then
967 Set_Color (Parent (X), Black);
968 Set_Color (Y, Black);
969 Set_Color (Parent (Parent (X)), Red);
970 X := Parent (Parent (X));
973 if X = Right (Parent (X)) then
975 Left_Rotate (Tree, X);
978 Set_Color (Parent (X), Black);
979 Set_Color (Parent (Parent (X)), Red);
980 Right_Rotate (Tree, Parent (Parent (X)));
984 pragma Assert (Parent (X) = Right (Parent (Parent (X))));
986 Y := Left (Parent (Parent (X)));
988 if Y /= null and then Color (Y) = Red then
989 Set_Color (Parent (X), Black);
990 Set_Color (Y, Black);
991 Set_Color (Parent (Parent (X)), Red);
992 X := Parent (Parent (X));
995 if X = Left (Parent (X)) then
997 Right_Rotate (Tree, X);
1000 Set_Color (Parent (X), Black);
1001 Set_Color (Parent (Parent (X)), Red);
1002 Left_Rotate (Tree, Parent (Parent (X)));
1007 Set_Color (Tree.Root, Black);
1008 end Rebalance_For_Insert;
1014 procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access) is
1015 X : constant Node_Access := Left (Y);
1016 pragma Assert (X /= null);
1019 Set_Left (Y, Right (X));
1021 if Right (X) /= null then
1022 Set_Parent (Right (X), Y);
1025 Set_Parent (X, Parent (Y));
1027 if Y = Tree.Root then
1029 elsif Y = Left (Parent (Y)) then
1030 Set_Left (Parent (Y), X);
1032 pragma Assert (Y = Right (Parent (Y)));
1033 Set_Right (Parent (Y), X);
1044 function Vet (Tree : Tree_Type; Node : Node_Access) return Boolean is
1050 if Parent (Node) = Node
1051 or else Left (Node) = Node
1052 or else Right (Node) = Node
1058 or else Tree.Root = null
1059 or else Tree.First = null
1060 or else Tree.Last = null
1065 if Parent (Tree.Root) /= null then
1069 if Left (Tree.First) /= null then
1073 if Right (Tree.Last) /= null then
1077 if Tree.Length = 1 then
1078 if Tree.First /= Tree.Last
1079 or else Tree.First /= Tree.Root
1084 if Node /= Tree.First then
1088 if Parent (Node) /= null
1089 or else Left (Node) /= null
1090 or else Right (Node) /= null
1098 if Tree.First = Tree.Last then
1102 if Tree.Length = 2 then
1103 if Tree.First /= Tree.Root
1104 and then Tree.Last /= Tree.Root
1109 if Tree.First /= Node
1110 and then Tree.Last /= Node
1116 if Left (Node) /= null
1117 and then Parent (Left (Node)) /= Node
1122 if Right (Node) /= null
1123 and then Parent (Right (Node)) /= Node
1128 if Parent (Node) = null then
1129 if Tree.Root /= Node then
1133 elsif Left (Parent (Node)) /= Node
1134 and then Right (Parent (Node)) /= Node
1142 end Ada.Containers.Red_Black_Trees.Generic_Operations;