// Quicksort // // Author: Rob Gysel // ECS60, UC Davis // Adapted from: Lysecky & Vahid "Data Structures Essentials", zyBooks #include "quicksort.h" int* QuickSort(std::vector* numbers) { int comparisonCounter = 0; int memAccessCounter = 0; static int returnCounters[2]; QuickSortRecurse(numbers, 0, numbers->size() - 1, &comparisonCounter, &memAccessCounter); returnCounters[0] = comparisonCounter; returnCounters[1] = memAccessCounter; return returnCounters; } void QuickSortRecurse(std::vector* numbers, int i, int k, int *comparisonCounter, int *memAccessCounter) { int j = 0; /* Base case: If there are 1 or zero elements to sort, partition is already sorted */ if (i >= k) { return; } /* Partition the data within the array. Value j returned from partitioning is location of last element in low partition. */ j = Partition(numbers, i, k, comparisonCounter, memAccessCounter); /* Recursively sort low partition (i to j) and high partition (j + 1 to k) */ QuickSortRecurse(numbers, i, j, comparisonCounter, memAccessCounter); QuickSortRecurse(numbers, j + 1, k, comparisonCounter, memAccessCounter); return; } int Partition(std::vector* numbers, int i, int k, int *comparisonCounter, int *memAccessCounter) { int l = 0; int h = 0; int midpoint = 0; int pivot = 0; int temp = 0; bool done = false; /* Pick middle element as pivot */ midpoint = i + (k - i) / 2; pivot = (*numbers)[midpoint]; *memAccessCounter = *memAccessCounter + 1; l = i; h = k; while (!done) { /* Increment l while numbers[l] < pivot */ while ((*numbers)[l] < pivot) { *comparisonCounter = *comparisonCounter + 1; *memAccessCounter = *memAccessCounter + 1; ++l; } // count the last loop's comparisons *comparisonCounter = *comparisonCounter + 1; *memAccessCounter = *memAccessCounter + 1; /* Decrement h while pivot < numbers[h] */ while (pivot < (*numbers)[h]) { *comparisonCounter = *comparisonCounter + 1; *memAccessCounter = *memAccessCounter + 1; --h; } // count the last loop's comparisons *comparisonCounter = *comparisonCounter + 1; *memAccessCounter = *memAccessCounter + 1; /* If there are zero or one elements remaining, all numbers are partitioned. Return h */ if (l >= h) { done = true; } else { /* Swap numbers[l] and numbers[h], update l and h */ temp = (*numbers)[l]; *memAccessCounter = *memAccessCounter + 1; (*numbers)[l] = (*numbers)[h]; *memAccessCounter = *memAccessCounter + 2; (*numbers)[h] = temp; *memAccessCounter = *memAccessCounter + 1; ++l; --h; } } return h; }