QUICKSORT.C
#include <stdlib.h>
#include <stdio.h>
#define INSERTION_SORT_BOUND 16 /* boundary point to use insertion sort */
#define uint32 unsigned int
typedef int (*CMPFUN)(int, int);
/* explain function
* Description:
* fixarray::Qsort() is an internal subroutine that implements quick sort.
*
* Return Value: none
*/
void Qsort(int This[], CMPFUN fun_ptr, uint32 first, uint32 last)
{
uint32 stack_pointer = 0;
int first_stack[32];
int last_stack[32];
for (;;)
{
if (last - first <= INSERTION_SORT_BOUND)
{
/* for small sort, use insertion sort */
uint32 indx;
int prev_val = This[first];
int cur_val;
for (indx = first + 1; indx <= last; ++indx)
{
cur_val = This[indx];
if ((*fun_ptr)(prev_val, cur_val) > 0)
{
/* out of order: array[indx-1] > array[indx] */
uint32 indx2;
This[indx] = prev_val; /* move up the larger item first */
/* find the insertion point for the smaller item */
for (indx2 = indx - 1; indx2 > first; )
{
int temp_val = This[indx2 - 1];
if ((*fun_ptr)(temp_val, cur_val) > 0)
{
This[indx2--] = temp_val;
/* still out of order, move up 1 slot to make room */
}
else
break;
}
This[indx2] = cur_val; /* insert the smaller item right here */
}
else
{
/* in order, advance to next element */
prev_val = cur_val;
}
}
}
else
{
int pivot;
/* try quick sort */
{
int temp;
uint32 med = (first + last) >> 1;
/* Choose pivot from first, last, and median position. */
/* Sort the three elements. */
temp = This[first];
if ((*fun_ptr)(temp, This[last]) > 0)
{
This[first] = This[last]; This[last] = temp;
}
temp = This[med];
if ((*fun_ptr)(This[first], temp) > 0)
{
This[med] = This[first]; This[first] = temp;
}
temp = This[last];
if ((*fun_ptr)(This[med], temp) > 0)
{
This[last] = This[med]; This[med] = temp;
}
pivot = This[med];
}
{
uint32 up;
{
uint32 down;
/* First and last element will be loop stopper. */
/* Split array into two partitions. */
down = first;
up = last;
for (;;)
{
do
{
++down;
} while ((*fun_ptr)(pivot, This[down]) > 0);
do
{
--up;
} while ((*fun_ptr)(This[up], pivot) > 0);
if (up > down)
{
int temp;
/* interchange L[down] and L[up] */
temp = This[down]; This[down]= This[up]; This[up] = temp;
}
else
break;
}
}
{
uint32 len1; /* length of first segment */
uint32 len2; /* length of second segment */
len1 = up - first + 1;
len2 = last - up;
/* stack the partition that is larger */
if (len1 >= len2)
{
first_stack[stack_pointer] = first;
last_stack[stack_pointer++] = up;
first = up + 1;
/* tail recursion elimination of
* Qsort(This,fun_ptr,up + 1,last)
*/
}
else
{
first_stack[stack_pointer] = up + 1;
last_stack[stack_pointer++] = last;
last = up;
/* tail recursion elimination of
* Qsort(This,fun_ptr,first,up)
*/
}
}
continue;
}
/* end of quick sort */
}
if (stack_pointer > 0)
{
/* Sort segment from stack. */
first = first_stack[--stack_pointer];
last = last_stack[stack_pointer];
}
else
break;
} /* end for */
}
void ArraySort(int This[], CMPFUN fun_ptr, uint32 the_len)
{
Qsort(This, fun_ptr, 0, the_len - 1);
}
#define ARRAY_SIZE 250000
int my_array[ARRAY_SIZE];
uint32 fill_array()
{
int indx;
uint32 checksum = 0;
for (indx=0; indx < ARRAY_SIZE; ++indx)
{
checksum += my_array[indx] = rand();
}
return checksum;
}
int cmpfun(int a, int b)
{
if (a > b)
return 1;
else if (a < b)
return -1;
else
return 0;
}
int main()
{
int indx;
uint32 checksum1;
uint32 checksum2 = 0;
checksum1 = fill_array();
ArraySort(my_array, cmpfun, ARRAY_SIZE);
for (indx=1; indx < ARRAY_SIZE; ++indx)
{
if (my_array[indx - 1] > my_array[indx])
{
printf("bad sort\n");
return(1);
}
}
for (indx=0; indx < ARRAY_SIZE; ++indx)
{
checksum2 += my_array[indx];
}
if (checksum1 != checksum2)
{
printf("bad checksum %d %d\n", checksum1, checksum2);
return(1);
}
return(0);
}
|