/* qsort.cpp * Date: 2024-06-22 * Author: Aryadev Chavali * Commentary: The inplace O(nlog(n)) sortitng algorithm. Originally designed * in C, hence the lack of iostream. */ #include #include #define ARR_SIZE(XS) (sizeof(XS) / sizeof((XS)[0])) #define SWAP(A, B) \ do \ { \ (A) ^= (B); \ (B) ^= (A); \ (A) ^= (B); \ } while (0) #define TEST_SIZE 10 void print_arr(int *arr, int size) { printf("{\n"); for (int i = 0; i < size; ++i) printf(" %d,\n", arr[i]); printf("}\n"); } void quicksort(int *arr, int arr_size) { #ifdef TRACE printf("before, arr="); print_arr(arr, arr_size); printf("\n"); #endif // TODO Optimisation: for small arr_size, a different sort like the bubble // sort may be better, instead of initialising new stack frames. if (arr_size < 2) return; // TODO Optimisation: Use some heuristics to figure out a better pivot than // some constant choice of element. int pivot = 0; int pivot_value = arr[0]; for (int i = 1; i < arr_size; ++i) { if (arr[i] <= pivot_value) { if (i != pivot) SWAP(arr[i], arr[pivot]); ++pivot; } } #ifdef TRACE printf("after, arr="); print_arr(arr, arr_size); printf("\n"); #endif // TODO Optimisation: Use a stack to do this instead of recursion. // // This algorithm is similar to a pre order traversal/dfs, in this case on an // array where left and right partition are children nodes to the original // array node. Also with recursion there's a real risk for very large // ARR_SIZE of running out of space in the call stack. if (pivot != 0) quicksort(arr, pivot); if (pivot < arr_size - 1) quicksort(arr + pivot + 1, arr_size - pivot - 1); } int main(void) { // randomly generate some numbers int *arr = new int[TEST_SIZE]; for (size_t i = 0; i < TEST_SIZE; ++i) { arr[i] = rand() % (2L << 30); } printf("Before: "); print_arr(arr, TEST_SIZE); printf("\n"); quicksort(arr, TEST_SIZE); printf("After: "); print_arr(arr, TEST_SIZE); printf("\n"); delete[] arr; return 0; }