|
1 | 1 | #include <stdio.h>
|
2 | 2 | #include <stdlib.h>
|
3 | 3 |
|
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 | + } |
51 | 33 | }
|
0 commit comments