1
-------------------------------------------------------------------------------
3
-- <STRONG>Copyright (c) 2001, 2002 by Thomas Wolf.</STRONG>
5
-- AdaBrowse is free software; you can redistribute it and/or modify it
6
-- under the terms of the GNU General Public License as published by the
7
-- Free Software Foundation; either version 2, or (at your option) any
8
-- later version. AdaBrowse is distributed in the hope that it will be
9
-- useful, but <EM>without any warranty</EM>; without even the implied
10
-- warranty of <EM>merchantability or fitness for a particular purpose.</EM>
11
-- See the GNU General Public License for more details. You should have
12
-- received a copy of the GNU General Public License with this distribution,
13
-- see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
14
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18
-- As a special exception from the GPL, if other files instantiate generics
19
-- from this unit, or you link this unit with other files to produce an
20
-- executable, this unit does not by itself cause the resulting executable
21
-- to be covered by the GPL. This exception does not however invalidate any
22
-- other reasons why the executable file might be covered by the GPL.
26
-- Author:</STRONG><DD>
28
-- <ADDRESS><A HREF="mailto:twolf@acm.org">twolf@acm.org</A></ADDRESS></DL>
31
-- Purpose:</STRONG><DD>
32
-- Generic list sorting operation with <CODE>O (n*log n)</CODE> worst-case
33
-- run-time complexity.
36
-- Tasking semantics:</STRONG><DD>
37
-- N/A. Not abortion-safe.</DL>
40
-- Storage semantics:</STRONG><DD>
41
-- No dynamic storage allocation. Uses <CODE>O (log n)</CODE> stack
47
-- 27-NOV-2001 TW Initial version.
48
-- 15-JAN-2002 TW Replaced natural merge sort by a direct method. (Both
49
-- are O(n*log n), but the natural merge sort has a higher
50
-- constant factor. In my performance tests, natural merge
51
-- sort was about three times slower. And, BTW, sorting an
52
-- array with GAL.Sorting.Sort_G was about 1.5 to 2 times
53
-- faster than this list sort.)
55
-------------------------------------------------------------------------------
57
pragma License (Modified_GPL);
59
-- To consider: shall I rewrite this in terms of a 'Position' type, like the
60
-- lexicographical comparisons?
63
-- type Node (<>) is limited private;
64
-- type Node_Ptr is access all Node;
65
-- with function "<" (L, R : in Node_Ptr) return Boolean;
67
-- with function Next (N : in Node_Ptr) return Node_Ptr;
68
-- with procedure Set_Next (N, Next : in Node_Ptr);
70
-- with procedure Post_Process (List, Last : in out Node_Ptr);
71
procedure GAL.Support.List_Sort
72
(List : in out Node_Ptr;
78
First, Last : Node_Ptr;
81
type Sequences is array (Boolean) of Sequence;
84
(Original : in out Sequence;
85
Work : in out Sequences);
86
pragma Inline (Split);
89
(Original : in out Sequence;
90
Work : in out Sequences)
92
P : Node_Ptr := Original.First;
94
On : Boolean := False;
100
exit when Q = null or else Q < R;
103
-- Append P .. R to Work (On).
104
if Work (On).First = null then
105
Work (On).First := P;
107
Set_Next (Work (On).Last, P);
113
Original.First := null; Original.Last := null;
114
if Work (False).First /= null then
115
Set_Next (Work (False).Last, null);
117
if Work (True).First /= null then
118
Set_Next (Work (True).Last, null);
123
(Work : in out Sequences;
124
Result : in out Sequence);
125
pragma Inline (Merge);
128
(Work : in out Sequences;
129
Result : in out Sequence)
133
while Work (False).First /= null and then Work (True).First /= null loop
134
if Work (True).First < Work (False).First then
135
P := Work (True).First;
136
Work (True).First := Next (P);
138
P := Work (False).First;
139
Work (False).First := Next (P);
141
if Result.First = null then
144
Set_Next (Result.Last, P);
149
if Work (False).First /= null then
150
P := Work (False).First;
151
Q := Work (False).Last;
152
Work (False).First := null;
153
elsif Work (True).First /= null then
154
P := Work (True).First;
155
Q := Work (True).Last;
156
Work (True).First := null;
159
if Result.First = null then
162
Set_Next (Result.Last, P);
166
Set_Next (Result.Last, null);
170
(List : in out Node_Ptr;
171
Last : out Node_Ptr);
172
pragma Inline (Sort);
175
(List : in out Node_Ptr;
178
Result : Sequence := (List, null);
182
if List = null or else Next (List) = null then
183
-- Zero or one element in the list: no need to sort.
186
-- We have at least two elements.
187
Split (Result, Work);
188
if Work (True).First /= null then
189
Sort (Work (False).First, Work (False).Last);
190
Sort (Work (True).First, Work (True).Last);
191
Merge (Work, Result);
193
Result := Work (False);
195
List := Result.First;
201
Post_Process (List, Last);
202
end GAL.Support.List_Sort;