/* * PREFIXED(quicksort).c - A simple, non-recursive, implementation of Quicksort * Samuel A. Rebelsky * Version 1.2 of 14 February 2007 */ /* * A PREFIXED(comparator) - yet to be defined formally - is a function * of two parameters, both BASETYPE. * It returns * negative, if the first is "less than" the secone * zero, if the two are equal * positive, if the first is greater than the second */ #include #include #define INITIAL_STACK_SIZE 16 /* Swap the elements at positions x and y */ void PREFIXED(swap)(BASETYPE a[], int x, int y) { int tmp = a[x]; a[x] = a[y]; a[y] = tmp; } /* PREFIXED(swap)(BASETYPE[], int, int) */ /* Copy the first n elements from source to target. */ void PREFIXED(copy)(BASETYPE source[], BASETYPE target[], int n) { int i; for (i = 0; i < n; i++) target[i] = source[i]; } /* PREFIXED(copy)(BASETYPE[], BASETYPE[], int) */ /* STACK STUFF */ /* Sam believes in stacks that can grow. */ BASETYPE *PREFIXED(stack) = (BASETYPE *) 0; /* The stack. */ int top = 0; /* The top of the stack. */ int size = 0; /* The current size of the stack. */ void PREFIXED(push)(BASETYPE val) { /* If no stack exists, create one. */ if (NULL == PREFIXED(stack)) { size = INITIAL_STACK_SIZE; PREFIXED(stack) = (BASETYPE *) malloc(INITIAL_STACK_SIZE * sizeof(BASETYPE)); top = 0; } /* If the stack is too small, expand it. */ if (size == top) { BASETYPE *newstack = (BASETYPE *) malloc(2*size*sizeof(BASETYPE)); /* WARNING! Did not check whether the result is null. */ int i; for (i = 0; i < size; i++) { newstack[i] = PREFIXED(stack)[i]; } free(PREFIXED(stack)); PREFIXED(stack) = newstack; size = 2*size; } /* We're FINALLY ready to PREFIXED(push) the value. */ PREFIXED(stack)[top++] = val; } /* PREFIXED(push)(BASETYPE) */ BASETYPE PREFIXED(pop)() { return PREFIXED(stack)[--top]; } /* PREFIXED(pop)() */ int PREFIXED(empty)() { return !top; } /* PREFIXED(empty)() */ int PREFIXED(partition)(BASETYPE a[], int start, int finish, PREFIXED(comparator) comp) { int left = start; int right = finish; BASETYPE pivot = a[start]; /* Repeatedly identify out-of-place elements and PREFIXED(swap) them. */ while (right > left) { /* Move right left until it points to an element smaller than the pivot. */ while ((right > left) && ((*comp)(a[right],pivot) >= 0)) right--; /* Move left right until it points to an element larger than the pivot. */ while ((right > left) && ((*comp)(a[left],pivot) <= 0)) left++; /* Swap! */ PREFIXED(swap)(a, left, right); } /* while */ /* Okay, both right and left point to something smaller than or equal to the pivot, so we can PREFIXED(swap). */ PREFIXED(swap)(a, start, left); return left; } /* PREFIXED(partition)(BASETYPE[], BASETYPE, BASETYPE, PREFIXED(comparator)) */ void PREFIXED(quicksort)(BASETYPE a[], int n, PREFIXED(comparator) comp) { if (n <= 1) return; PREFIXED(push)(0); PREFIXED(push)(n-1); while (!PREFIXED(empty)()) { int finish = PREFIXED(pop)(); int start = PREFIXED(pop)(); int mid = PREFIXED(partition)(a, start, finish, comp); if (mid+1 < finish) { PREFIXED(push)(mid+1); PREFIXED(push)(finish); } if (mid-1 > start) { PREFIXED(push)(start); PREFIXED(push)(mid-1); } } /* while (!PREFIXED(empty)() */ } /* PREFIXED(quicksort)(BASETYPE[], int) */