Skip to content

Commit 396a5ce

Browse files
committed
Rewriting qsort to handle unstable comparison functions.
1 parent b0e0853 commit 396a5ce

File tree

1 file changed

+29
-47
lines changed

1 file changed

+29
-47
lines changed

libc/src/qsort.c

Lines changed: 29 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,33 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33

4-
/* sample compar function: int cmp(void *a,void *b){ return *(int *)a-*(int *)b; } */
5-
6-
/* This qsort function does a little trick:
7-
* To reduce stackspace it iterates the larger interval instead of doing
8-
* the recursion on both intervals.
9-
* So stackspace is limited to 32*stack_for_1_iteration =
10-
* 32*4*(4 arguments+1 returnaddress+11 stored registers) = 2048 Bytes,
11-
* which is small enough for everybodys use.
12-
* (And this is the worst case if you own 4GB and sort an array of chars.)
13-
* Sparing the function calling overhead does improve performance, too.
14-
*/
15-
16-
void qsort
17-
(void *base,size_t nmemb,size_t size,int (*compar)(const void *,const void *))
18-
{ char *base2=(char *)base;
19-
size_t i,a,b,c;
20-
while(nmemb>1)
21-
{ a=0;
22-
b=nmemb-1;
23-
c=(a+b)/2; /* Middle element */
24-
for(;;)
25-
{ while((*compar)(&base2[size*c],&base2[size*a])>0)
26-
a++; /* Look for one >= middle */
27-
while((*compar)(&base2[size*c],&base2[size*b])<0)
28-
b--; /* Look for one <= middle */
29-
if(a>=b)
30-
break; /* We found no pair */
31-
for(i=0;i<size;i++) /* swap them */
32-
{ char tmp=base2[size*a+i];
33-
base2[size*a+i]=base2[size*b+i];
34-
base2[size*b+i]=tmp; }
35-
if(c==a) /* Keep track of middle element */
36-
c=b;
37-
else if(c==b)
38-
c=a;
39-
a++; /* These two are already sorted */
40-
b--;
41-
} /* a points to first element of right intervall now (b to last of left) */
42-
b++;
43-
if(b<nmemb-b) /* do recursion on smaller intervall and iteration on larger one */
44-
{ qsort(base2,b,size,compar);
45-
base2=&base2[size*b];
46-
nmemb=nmemb-b; }
47-
else
48-
{ qsort(&base2[size*b],nmemb-b,size,compar);
49-
nmemb=b; }
50-
}
4+
void qsort(void *base, size_t num, size_t size, int (*cmp)(const void *, const void *)) {
5+
size_t gap, i, j, k;
6+
if ((num > 1) && (size > 0)) {
7+
gap = 0;
8+
while (gap < (num - 1) / 3) gap = 3 * gap + 1;
9+
gap *= size;
10+
num *= size;
11+
while (gap != 0) {
12+
i = gap;
13+
while (i < num) {
14+
j = i;
15+
while (j >= gap) {
16+
char *a, *b;
17+
j -= gap;
18+
a = j + ((char *)base);
19+
b = a + gap;
20+
if ((*cmp)(a, b) <= 0) break;
21+
k = size;
22+
while (k--) {
23+
char tmp = *a;
24+
*a++ = *b;
25+
*b++ = tmp;
26+
}
27+
}
28+
i += size;
29+
}
30+
gap = (gap - size) / 3;
31+
}
32+
}
5133
}

0 commit comments

Comments
 (0)