radixsort.c revision 1.1 1 1.1 cgd /*-
2 1.1 cgd * Copyright (c) 1990 The Regents of the University of California.
3 1.1 cgd * All rights reserved.
4 1.1 cgd *
5 1.1 cgd * Redistribution and use in source and binary forms, with or without
6 1.1 cgd * modification, are permitted provided that the following conditions
7 1.1 cgd * are met:
8 1.1 cgd * 1. Redistributions of source code must retain the above copyright
9 1.1 cgd * notice, this list of conditions and the following disclaimer.
10 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer in the
12 1.1 cgd * documentation and/or other materials provided with the distribution.
13 1.1 cgd * 3. All advertising materials mentioning features or use of this software
14 1.1 cgd * must display the following acknowledgement:
15 1.1 cgd * This product includes software developed by the University of
16 1.1 cgd * California, Berkeley and its contributors.
17 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
18 1.1 cgd * may be used to endorse or promote products derived from this software
19 1.1 cgd * without specific prior written permission.
20 1.1 cgd *
21 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1 cgd * SUCH DAMAGE.
32 1.1 cgd */
33 1.1 cgd
34 1.1 cgd #if defined(LIBC_SCCS) && !defined(lint)
35 1.1 cgd static char sccsid[] = "@(#)radixsort.c 5.7 (Berkeley) 2/23/91";
36 1.1 cgd #endif /* LIBC_SCCS and not lint */
37 1.1 cgd
38 1.1 cgd #include <sys/types.h>
39 1.1 cgd #include <limits.h>
40 1.1 cgd #include <stdlib.h>
41 1.1 cgd #include <stddef.h>
42 1.1 cgd #include <string.h>
43 1.1 cgd
44 1.1 cgd /*
45 1.1 cgd * __rspartition is the cutoff point for a further partitioning instead
46 1.1 cgd * of a shellsort. If it changes check __rsshell_increments. Both of
47 1.1 cgd * these are exported, as the best values are data dependent.
48 1.1 cgd */
49 1.1 cgd #define NPARTITION 40
50 1.1 cgd int __rspartition = NPARTITION;
51 1.1 cgd int __rsshell_increments[] = { 4, 1, 0, 0, 0, 0, 0, 0 };
52 1.1 cgd
53 1.1 cgd /*
54 1.1 cgd * Stackp points to context structures, where each structure schedules a
55 1.1 cgd * partitioning. Radixsort exits when the stack is empty.
56 1.1 cgd *
57 1.1 cgd * If the buckets are placed on the stack randomly, the worst case is when
58 1.1 cgd * all the buckets but one contain (npartitions + 1) elements and the bucket
59 1.1 cgd * pushed on the stack last contains the rest of the elements. In this case,
60 1.1 cgd * stack growth is bounded by:
61 1.1 cgd *
62 1.1 cgd * limit = (nelements / (npartitions + 1)) - 1;
63 1.1 cgd *
64 1.1 cgd * This is a very large number, 52,377,648 for the maximum 32-bit signed int.
65 1.1 cgd *
66 1.1 cgd * By forcing the largest bucket to be pushed on the stack first, the worst
67 1.1 cgd * case is when all but two buckets each contain (npartitions + 1) elements,
68 1.1 cgd * with the remaining elements split equally between the first and last
69 1.1 cgd * buckets pushed on the stack. In this case, stack growth is bounded when:
70 1.1 cgd *
71 1.1 cgd * for (partition_cnt = 0; nelements > npartitions; ++partition_cnt)
72 1.1 cgd * nelements =
73 1.1 cgd * (nelements - (npartitions + 1) * (nbuckets - 2)) / 2;
74 1.1 cgd * The bound is:
75 1.1 cgd *
76 1.1 cgd * limit = partition_cnt * (nbuckets - 1);
77 1.1 cgd *
78 1.1 cgd * This is a much smaller number, 4590 for the maximum 32-bit signed int.
79 1.1 cgd */
80 1.1 cgd #define NBUCKETS (UCHAR_MAX + 1)
81 1.1 cgd
82 1.1 cgd typedef struct _stack {
83 1.1 cgd const u_char **bot;
84 1.1 cgd int indx, nmemb;
85 1.1 cgd } CONTEXT;
86 1.1 cgd
87 1.1 cgd #define STACKPUSH { \
88 1.1 cgd stackp->bot = p; \
89 1.1 cgd stackp->nmemb = nmemb; \
90 1.1 cgd stackp->indx = indx; \
91 1.1 cgd ++stackp; \
92 1.1 cgd }
93 1.1 cgd #define STACKPOP { \
94 1.1 cgd if (stackp == stack) \
95 1.1 cgd break; \
96 1.1 cgd --stackp; \
97 1.1 cgd bot = stackp->bot; \
98 1.1 cgd nmemb = stackp->nmemb; \
99 1.1 cgd indx = stackp->indx; \
100 1.1 cgd }
101 1.1 cgd
102 1.1 cgd /*
103 1.1 cgd * A variant of MSD radix sorting; see Knuth Vol. 3, page 177, and 5.2.5,
104 1.1 cgd * Ex. 10 and 12. Also, "Three Partition Refinement Algorithms, Paige
105 1.1 cgd * and Tarjan, SIAM J. Comput. Vol. 16, No. 6, December 1987.
106 1.1 cgd *
107 1.1 cgd * This uses a simple sort as soon as a bucket crosses a cutoff point,
108 1.1 cgd * rather than sorting the entire list after partitioning is finished.
109 1.1 cgd * This should be an advantage.
110 1.1 cgd *
111 1.1 cgd * This is pure MSD instead of LSD of some number of MSD, switching to
112 1.1 cgd * the simple sort as soon as possible. Takes linear time relative to
113 1.1 cgd * the number of bytes in the strings.
114 1.1 cgd */
115 1.1 cgd int
116 1.1 cgd #if __STDC__
117 1.1 cgd radixsort(const u_char **l1, int nmemb, const u_char *tab, u_char endbyte)
118 1.1 cgd #else
119 1.1 cgd radixsort(l1, nmemb, tab, endbyte)
120 1.1 cgd const u_char **l1;
121 1.1 cgd register int nmemb;
122 1.1 cgd const u_char *tab;
123 1.1 cgd u_char endbyte;
124 1.1 cgd #endif
125 1.1 cgd {
126 1.1 cgd register int i, indx, t1, t2;
127 1.1 cgd register const u_char **l2;
128 1.1 cgd register const u_char **p;
129 1.1 cgd register const u_char **bot;
130 1.1 cgd register const u_char *tr;
131 1.1 cgd CONTEXT *stack, *stackp;
132 1.1 cgd int c[NBUCKETS + 1], max;
133 1.1 cgd u_char ltab[NBUCKETS];
134 1.1 cgd static void shellsort();
135 1.1 cgd
136 1.1 cgd if (nmemb <= 1)
137 1.1 cgd return(0);
138 1.1 cgd
139 1.1 cgd /*
140 1.1 cgd * T1 is the constant part of the equation, the number of elements
141 1.1 cgd * represented on the stack between the top and bottom entries.
142 1.1 cgd * It doesn't get rounded as the divide by 2 rounds down (correct
143 1.1 cgd * for a value being subtracted). T2, the nelem value, has to be
144 1.1 cgd * rounded up before each divide because we want an upper bound;
145 1.1 cgd * this could overflow if nmemb is the maximum int.
146 1.1 cgd */
147 1.1 cgd t1 = ((__rspartition + 1) * (NBUCKETS - 2)) >> 1;
148 1.1 cgd for (i = 0, t2 = nmemb; t2 > __rspartition; i += NBUCKETS - 1)
149 1.1 cgd t2 = ((t2 + 1) >> 1) - t1;
150 1.1 cgd if (i) {
151 1.1 cgd if (!(stack = stackp = (CONTEXT *)malloc(i * sizeof(CONTEXT))))
152 1.1 cgd return(-1);
153 1.1 cgd } else
154 1.1 cgd stack = stackp = NULL;
155 1.1 cgd
156 1.1 cgd /*
157 1.1 cgd * There are two arrays, one provided by the user (l1), and the
158 1.1 cgd * temporary one (l2). The data is sorted to the temporary stack,
159 1.1 cgd * and then copied back. The speedup of using index to determine
160 1.1 cgd * which stack the data is on and simply swapping stacks back and
161 1.1 cgd * forth, thus avoiding the copy every iteration, turns out to not
162 1.1 cgd * be any faster than the current implementation.
163 1.1 cgd */
164 1.1 cgd if (!(l2 = (const u_char **)malloc(sizeof(u_char *) * nmemb)))
165 1.1 cgd return(-1);
166 1.1 cgd
167 1.1 cgd /*
168 1.1 cgd * Tr references a table of sort weights; multiple entries may
169 1.1 cgd * map to the same weight; EOS char must have the lowest weight.
170 1.1 cgd */
171 1.1 cgd if (tab)
172 1.1 cgd tr = tab;
173 1.1 cgd else {
174 1.1 cgd for (t1 = 0, t2 = endbyte; t1 < t2; ++t1)
175 1.1 cgd ltab[t1] = t1 + 1;
176 1.1 cgd ltab[t2] = 0;
177 1.1 cgd for (t1 = endbyte + 1; t1 < NBUCKETS; ++t1)
178 1.1 cgd ltab[t1] = t1;
179 1.1 cgd tr = ltab;
180 1.1 cgd }
181 1.1 cgd
182 1.1 cgd /* First sort is entire stack */
183 1.1 cgd bot = l1;
184 1.1 cgd indx = 0;
185 1.1 cgd
186 1.1 cgd for (;;) {
187 1.1 cgd /* Clear bucket count array */
188 1.1 cgd bzero((char *)c, sizeof(c));
189 1.1 cgd
190 1.1 cgd /*
191 1.1 cgd * Compute number of items that sort to the same bucket
192 1.1 cgd * for this index.
193 1.1 cgd */
194 1.1 cgd for (p = bot, i = nmemb; --i >= 0;)
195 1.1 cgd ++c[tr[(*p++)[indx]]];
196 1.1 cgd
197 1.1 cgd /*
198 1.1 cgd * Sum the number of characters into c, dividing the temp
199 1.1 cgd * stack into the right number of buckets for this bucket,
200 1.1 cgd * this index. C contains the cumulative total of keys
201 1.1 cgd * before and included in this bucket, and will later be
202 1.1 cgd * used as an index to the bucket. c[NBUCKETS] contains
203 1.1 cgd * the total number of elements, for determining how many
204 1.1 cgd * elements the last bucket contains. At the same time
205 1.1 cgd * find the largest bucket so it gets pushed first.
206 1.1 cgd */
207 1.1 cgd for (i = max = t1 = 0, t2 = __rspartition; i <= NBUCKETS; ++i) {
208 1.1 cgd if (c[i] > t2) {
209 1.1 cgd t2 = c[i];
210 1.1 cgd max = i;
211 1.1 cgd }
212 1.1 cgd t1 = c[i] += t1;
213 1.1 cgd }
214 1.1 cgd
215 1.1 cgd /*
216 1.1 cgd * Partition the elements into buckets; c decrements through
217 1.1 cgd * the bucket, and ends up pointing to the first element of
218 1.1 cgd * the bucket.
219 1.1 cgd */
220 1.1 cgd for (i = nmemb; --i >= 0;) {
221 1.1 cgd --p;
222 1.1 cgd l2[--c[tr[(*p)[indx]]]] = *p;
223 1.1 cgd }
224 1.1 cgd
225 1.1 cgd /* Copy the partitioned elements back to user stack */
226 1.1 cgd bcopy(l2, bot, nmemb * sizeof(u_char *));
227 1.1 cgd
228 1.1 cgd ++indx;
229 1.1 cgd /*
230 1.1 cgd * Sort buckets as necessary; don't sort c[0], it's the
231 1.1 cgd * EOS character bucket, and nothing can follow EOS.
232 1.1 cgd */
233 1.1 cgd for (i = max; i; --i) {
234 1.1 cgd if ((nmemb = c[i + 1] - (t1 = c[i])) < 2)
235 1.1 cgd continue;
236 1.1 cgd p = bot + t1;
237 1.1 cgd if (nmemb > __rspartition)
238 1.1 cgd STACKPUSH
239 1.1 cgd else
240 1.1 cgd shellsort(p, indx, nmemb, tr);
241 1.1 cgd }
242 1.1 cgd for (i = max + 1; i < NBUCKETS; ++i) {
243 1.1 cgd if ((nmemb = c[i + 1] - (t1 = c[i])) < 2)
244 1.1 cgd continue;
245 1.1 cgd p = bot + t1;
246 1.1 cgd if (nmemb > __rspartition)
247 1.1 cgd STACKPUSH
248 1.1 cgd else
249 1.1 cgd shellsort(p, indx, nmemb, tr);
250 1.1 cgd }
251 1.1 cgd /* Break out when stack is empty */
252 1.1 cgd STACKPOP
253 1.1 cgd }
254 1.1 cgd
255 1.1 cgd free((char *)l2);
256 1.1 cgd free((char *)stack);
257 1.1 cgd return(0);
258 1.1 cgd }
259 1.1 cgd
260 1.1 cgd /*
261 1.1 cgd * Shellsort (diminishing increment sort) from Data Structures and
262 1.1 cgd * Algorithms, Aho, Hopcraft and Ullman, 1983 Edition, page 290;
263 1.1 cgd * see also Knuth Vol. 3, page 84. The increments are selected from
264 1.1 cgd * formula (8), page 95. Roughly O(N^3/2).
265 1.1 cgd */
266 1.1 cgd static void
267 1.1 cgd shellsort(p, indx, nmemb, tr)
268 1.1 cgd register u_char **p, *tr;
269 1.1 cgd register int indx, nmemb;
270 1.1 cgd {
271 1.1 cgd register u_char ch, *s1, *s2;
272 1.1 cgd register int incr, *incrp, t1, t2;
273 1.1 cgd
274 1.1 cgd for (incrp = __rsshell_increments; incr = *incrp++;)
275 1.1 cgd for (t1 = incr; t1 < nmemb; ++t1)
276 1.1 cgd for (t2 = t1 - incr; t2 >= 0;) {
277 1.1 cgd s1 = p[t2] + indx;
278 1.1 cgd s2 = p[t2 + incr] + indx;
279 1.1 cgd while ((ch = tr[*s1++]) == tr[*s2] && ch)
280 1.1 cgd ++s2;
281 1.1 cgd if (ch > tr[*s2]) {
282 1.1 cgd s1 = p[t2];
283 1.1 cgd p[t2] = p[t2 + incr];
284 1.1 cgd p[t2 + incr] = s1;
285 1.1 cgd t2 -= incr;
286 1.1 cgd } else
287 1.1 cgd break;
288 1.1 cgd }
289 1.1 cgd }
290