/* quicksort and select as taken from CLR. -bds 9/95 */ #include "sort.h" /* sort.h defines types Key, Record, Entry = struct{Key key, Record r}, and procedure swap. and comparison operators on type Key (>, <=, <, >=, ==, !=). */ Entry Slick_Select(Entry* A, int p, int r, int i); int Slick_Partition(Entry* A, int p, int r) /* Assumes p <= r are valid indices for A. Returns index q, p <= q < r and permutes A so that A[p] thru A[q] are <= x and A[q+1] thru A[r] are >= x. where x is A[i] and p <= i <= r. It is guaranteed that partition is relatively even, to be precise, for large n = r - p + 1, the sizes q - p + 1 and r - q + 1 of the two partitions are both >= 3n/10 - 3. As a side effect, A is permuted (but not completely sorted). */{ Entry* B; int n = r - p + 1; int k = n/5; // floor. B = malloc( (k+1)*sizeof(Entry) );/* could avoid using extra space like this */ for (int i = 1, i <= k; i += 5) { Anysort(A, i, i+4); B[i] = A[i+2]; } Entry x = Slick_Select(B, 1, k, k/2); return Partition(A, p, r, x.key); } Entry Slick_Select(Entry* A, int p, int r, int i) /* Assumes 1 <= i <= r - p + 1 and Returns the i-th smallest element of A[p] thru A[r], i.e. returns A'[i], where A' denotes what A would be if A[p] thru A[r] were sorted into increasing order. As a side effect, A is permuted (but not completely sorted). */{ if (p >= r) return A[p]; else { int q = Slick_Partition(A, p, r), ; int k = q - p + 1; // k = size of lower partition. if (i <= k) return Slick_Select(A, p, q, i); else return Slick_Select(A, q+1, r, i - k); } } /* Theorem 1: Slick_Partition delivers on it's claim, "the partition sizes are both >= 3n/10 - 4". Proof summary: Entries less than x are three in each of about half the groups of 5. Theorem 2: for n = r - p + 1, Slick_Select(A, p, q, i) and Slick_Partition(A, p, q, x) both run in theta(n) time. Proof summary: Let S(n) = time for Slick_Select and let P(n) = time for Slick_Partition. Then by examining the code we see the recurrences: S(n) <= P(n) + S(7n/10 + 4) + C, for some constant C P(n) = theta(n) + S(n/5). Show by induction that S(n) <= D*n, if D >= 20*C and D >= S(1). */ void Slick_Quicksort(Entry* A, int p, int r) /* Assumes p <= r are valid indices for A. Permutes A so that A[p] thru A[r] are in increasing order. */{ if (p < r) { int q = Slick_Partition(A, p, r, A[p]); Slick_Quicksort(A, p, q); Slick_Quicksort(A, q+1, r); }