home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 4
/
DATAFILE_PDCD4.iso
/
unix
/
unixlib36d
/
src
/
c
/
qsort
< prev
next >
Wrap
Text File
|
1994-03-08
|
4KB
|
216 lines
#ifdef __STDC__
static char sccs_id[] = "@(#) qsort.c 2.3 " __DATE__ " HJR";
#else
static char sccs_id[] = "@(#) qsort.c 2.3 26/9/90 HJR";
#endif
/* qsort.c (c) Copyright 1990 H.Rogers */
#ifdef __STDC__
#include <stddef.h>
#include <stdlib.h>
#else
#include "sys/types.h"
extern void qsort ();
#endif
#include <string.h>
#define N_INSERT 8
static char *__t;
static size_t __z;
#ifdef __STDC__
static int (*__c) (const void *, const void *);
#else
static int (*__c) ();
#endif
/* fast insertion sort - used for n <= N_INSERT */
#ifdef __STDC__
static void
__isort (register char *b, register size_t n)
#else
static void
__isort (b, n)
register char *b;
register size_t n;
#endif
{
register size_t z = __z;
#ifdef __STDC__
register int (*c) (const void *, const void *) = __c;
#else
register int (*c) () = __c;
#endif
register char *m, *e, *p;
register char *t;
#define swap(x,y) (memcpy(t,x,z),memcpy(x,y,z),memcpy(y,t,z))
#define move(x,y,z) memmove(x,y,z)
#define push(x) memcpy(t,x,z)
#define pull(x) memcpy(x,t,z)
t = __t;
e = b + (n * z); /* past end */
/* find minimum */
for (m = p = b; (p += z) < e;)
if ((*c) (m, p) > 0)
m = p;
/* swap minimum into base */
if (m != b)
swap (m, b);
/* standard insertion sort */
for (m = b; (p = m += z) < e;)
{
while ((*c) (p -= z, m) > 0);
if ((p += z) != m)
push (m), move (p + z, p, m - p), pull (p);
}
#undef swap
#undef move
#undef push
#undef pull
}
/* quicksort - used for n > N_INSERT */
#ifdef __STDC__
static void
__qsort (register char *b, register size_t n)
#else
static void
__qsort (b, n)
register char *b;
register size_t n;
#endif
{
register size_t z = __z;
#ifdef __STDC__
register int (*c) (const void *, const void *) = __c;
#else
register int (*c) () = __c;
#endif
register char *m, *e, *p, *t;
register int i, j, k;
#define swap(x,y) (memcpy(t,x,z),memcpy(x,y,z),memcpy(y,t,z))
loop:
t = __t;
m = b + ((n >> 1) * z); /* middle */
e = b + ((n - 1) * z); /* end */
/* find pivot - median of b,m,e */
if ((*c) (b, m) >= 0)
p = b;
else
p = m, m = b;
if ((*c) (p, e) > 0)
p = ((*c) (m, e) >= 0) ? m : e;
/* swap pivot into base */
if (p != b)
swap (p, b);
/* standard quicksort & check for flat partition */
m = b;
i = 0;
j = 1;
for (p = b; (p += z) <= e;)
{
if (!(k = (*c) (p, b)))
j++;
if (k < 0)
{
if ((m += z) != p)
swap (m, p);
i++;
}
}
if (j == n)
return; /* exit if flat */
if (b != m)
swap (b, m);
m += z;
/* sort smallest partition first */
if (i < (n >> 1))
{
if (i > N_INSERT)
__qsort (b, i);
else if (i > 1)
__isort (b, i);
i = n - i - 1;
}
else
{
i = n - i - 1;
if (i > N_INSERT)
__qsort (m, i);
else if (i > 1)
__isort (m, i);
i = n - i - 1;
m = b;
}
if (i > N_INSERT)
{
b = m;
n = i;
goto loop;
} /* iterate larger partition */
else if (i > 1)
__isort (m, i);
#undef swap
}
#ifdef __STDC__
void
qsort (register void *v, register size_t n, register size_t z,
register int (*c) (const void *, const void *))
#else
void
qsort (v, n, z, c)
register void *v;
register size_t n;
register size_t z;
register int (*c) ();
#endif
{
if (n < 2)
return;
if (!(__t = malloc (z)))
return;
__z = z;
__c = c;
if (n > N_INSERT)
__qsort ((char *) v, n);
else if (n > 1)
__isort ((char *) v, n);
free (__t);
}