#include #include #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); }