The question you link to (C library function to do sort) shows how to use the standard C library function called qsort()
in general, but your requirement is not one of the usual problems. To be able to sort the oo
array, the comparator function must be able access the x
array as well as the data passed to it from qsort()
itself.
This code achieves that with reasonable economy of effort:
#include <stdio.h>
#include <stdlib.h>
typedef double VecType;
#define PRIf_VecType "f"
static VecType *base;
static int compare(const void *p1, const void *p2)
{
const int i1 = *(int *)p1;
const int i2 = *(int *)p2;
if (base[i1] < base[i2])
return -1;
else if (base[i1] > base[i2])
return +1;
else
return 0;
}
static void print_arrays(const char *tag, size_t x_size, VecType *x, int *oo)
{
printf("%s:\n", tag);
for (size_t i = 0; i < x_size; i++)
printf("%zu: oo[%zu] = %d, x[oo[%zu]] = %4.2" PRIf_VecType
", x[%zu] = %4.2" PRIf_VecType "\n",
i, i, oo[i], i, x[oo[i]], i, x[i]);
}
int main(void)
{
VecType x[] = { 3.45, 1.23, 9.14, 4.67, 2.19, 3.45, 5.92 };
size_t x_size = sizeof(x) / sizeof(x[0]);
int oo[x_size];
for (size_t i = 0; i < x_size; i++)
oo[i] = (int)i;
print_arrays("Before", x_size, x, oo);
base = x;
qsort(oo, x_size, sizeof(oo[0]), compare);
print_arrays("After", x_size, x, oo);
return 0;
}
Sample output:
Before:
0: oo[0] = 0, x[oo[0]] = 3.45, x[0] = 3.45
1: oo[1] = 1, x[oo[1]] = 1.23, x[1] = 1.23
2: oo[2] = 2, x[oo[2]] = 9.14, x[2] = 9.14
3: oo[3] = 3, x[oo[3]] = 4.67, x[3] = 4.67
4: oo[4] = 4, x[oo[4]] = 2.19, x[4] = 2.19
5: oo[5] = 5, x[oo[5]] = 3.45, x[5] = 3.45
6: oo[6] = 6, x[oo[6]] = 5.92, x[6] = 5.92
After:
0: oo[0] = 1, x[oo[0]] = 1.23, x[0] = 3.45
1: oo[1] = 4, x[oo[1]] = 2.19, x[1] = 1.23
2: oo[2] = 5, x[oo[2]] = 3.45, x[2] = 9.14
3: oo[3] = 0, x[oo[3]] = 3.45, x[3] = 4.67
4: oo[4] = 3, x[oo[4]] = 4.67, x[4] = 2.19
5: oo[5] = 6, x[oo[5]] = 5.92, x[5] = 3.45
6: oo[6] = 2, x[oo[6]] = 9.14, x[6] = 5.92
The printing for 'after' assures us that the array x
is unchanged, but the array oo
has been updated such that x[oo[i]]
is in the i
th position in sorted order.
BSD (and therefore Mac OS X too) provides a non-standard alternative to qsort()
, namely qsort_r()
:
void qsort_r(void *base, size_t nel, size_t width, void *thunk,
int (*compar)(void *, const void *, const void *));
The qsort_r()
function behaves identically to qsort()
, except that it takes an additional argument, thunk
, which is passed unchanged as the first argument to function pointed to compar
. This allows the comparison function to access additional data without using global variables, and thus qsort_r()
is suitable for use in functions which must be reentrant.
Writing the code in terms of qsort_r()
is a rather trivial set of changes:
#include <stdio.h>
#include <stdlib.h>
typedef double VecType;
#define PRIf_VecType "f"
static int compare(void *thunk, const void *p1, const void *p2)
{
const VecType *base = (VecType *)thunk;
const int i1 = *(int *)p1;
const int i2 = *(int *)p2;
if (base[i1] < base[i2])
return -1;
else if (base[i1] > base[i2])
return +1;
else
return 0;
}
static void print_arrays(const char *tag, size_t x_size, VecType *x, int *oo)
{
printf("%s:\n", tag);
for (size_t i = 0; i < x_size; i++)
printf("%zu: oo[%zu] = %d, x[oo[%zu]] = %4.2" PRIf_VecType
", x[%zu] = %4.2" PRIf_VecType "\n",
i, i, oo[i], i, x[oo[i]], i, x[i]);
}
int main(void)
{
VecType x[] = { 3.45, 1.23, 9.14, 4.67, 2.19, 3.45, 5.92 };
size_t x_size = sizeof(x) / sizeof(x[0]);
int oo[x_size];
for (size_t i = 0; i < x_size; i++)
oo[i] = (int)i;
print_arrays("Before", x_size, x, oo);
qsort_r(oo, x_size, sizeof(oo[0]), x, compare);
print_arrays("After", x_size, x, oo);
return 0;
}
With sample output like this (it is the same as the output from the other code):
Before:
0: oo[0] = 0, x[oo[0]] = 3.45, x[0] = 3.45
1: oo[1] = 1, x[oo[1]] = 1.23, x[1] = 1.23
2: oo[2] = 2, x[oo[2]] = 9.14, x[2] = 9.14
3: oo[3] = 3, x[oo[3]] = 4.67, x[3] = 4.67
4: oo[4] = 4, x[oo[4]] = 2.19, x[4] = 2.19
5: oo[5] = 5, x[oo[5]] = 3.45, x[5] = 3.45
6: oo[6] = 6, x[oo[6]] = 5.92, x[6] = 5.92
After:
0: oo[0] = 1, x[oo[0]] = 1.23, x[0] = 3.45
1: oo[1] = 4, x[oo[1]] = 2.19, x[1] = 1.23
2: oo[2] = 5, x[oo[2]] = 3.45, x[2] = 9.14
3: oo[3] = 0, x[oo[3]] = 3.45, x[3] = 4.67
4: oo[4] = 3, x[oo[4]] = 4.67, x[4] = 2.19
5: oo[5] = 6, x[oo[5]] = 5.92, x[5] = 3.45
6: oo[6] = 2, x[oo[6]] = 9.14, x[6] = 5.92