Histogram sort for integers (fast)This is a histogram sort for signed integers. It is about three times as fast as qsort.
/*
* Copyright (c) 2004 by Richard Harter.
* This software may be freely used and modified without
* restriction provided that this notice is preserved unaltered.
*
*/
/*
* This function sorts an array of integers in place using a math
* sort based histogram sort. 2*len locations of auxilliary space
* are used, where len is the data length.
*/
#include <stdlib.h>
#define MIN_SORTABLE_LENGTH 128
#define PROCESSED -1
int
int_msort(int * data, int len)
{
int data_min; /* Minimum value in data array */
int data_max; /* Maximum value in data array */
int index_min; /* Index of minimum value */
int i; /* Major loop index */
int j; /* Minor loop index */
int ifac; /* Integer scaling factor */
int temp; /* Temp loc for data moves */
int *space; /* Ptr to allocated space */
int *cmp_index; /* Ptr to computed indices */
int *cum; /* Ptr to cumulative distrib. */
int *hist; /* Ptr to cumulative distrib. */
int *sorted; /* Ptr to almost sorted data */
if (len <= 1) return 1;
if (len == 2) {
if (data[0] > data[1]) {
temp = data[0];
data[0] = data[1];
data[1] = temp;
}
return 1;
}
data_min = data[0];
data_max = data[0];
index_min = 0;
for (i=len; --i>0;) {
if (data[i] < data_min) {
data_min = data[i];
index_min = i;
}
}
if (index_min != 0) {
data[index_min] = data[0];
data[0] = data_min;
}
if (len >= MIN_SORTABLE_LENGTH) {
for (i=len; --i>0;) {
if (data[i] > data_max) data_max = data[i];
}
/* Compute interpolation function */
ifac = (data_max - data_min)/(len -1);
if (ifac<=0) ifac=1;
else while (((data_max-data_min)/ifac)>(len-1)) ifac++;
/* allocate index and histogram space */
space = malloc((2*len+1)*sizeof(int));
if (!space) return 0;
cmp_index = space;
cum = space + len;
hist = cum + 1;
sorted = hist;
memset(cum,0,(len+1)*sizeof(int));
/* Compute raw interpolation indices */
for (i=len; --i>=0;) {
hist[cmp_index[i] = (data[i] - data_min)/ifac] += 1;
}
for (i=1;i<len;i++) cum[i] += cum[i-1];
for (i=0;i<len;i++) cmp_index[i] = cum[cmp_index[i]]++;
/* Math sort proper */
for (i=len; --i >= 0;) sorted[cmp_index[i]] = data[i];
memcpy(data, sorted, len*sizeof(int));
free (space);
}
/* End of math sort section, begin insertion sort section */
{
for (i=1; i<len; i++) {
if (data[i] >= data[i-1]) continue;
temp = data[i];
data[i] = data[i-1];
for (j = i-2; temp < data[j]; j--) data[j+1] = data[j];
data[j+1] = temp;
}
}
return 1;
}
This page was last updated January 15, 2005. |