quicksort.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Quicksort
  2. //
  3. // Author: Rob Gysel
  4. // ECS60, UC Davis
  5. // Adapted from: Lysecky & Vahid "Data Structures Essentials", zyBooks
  6. #include "quicksort.h"
  7. int* QuickSort(std::vector<int>* numbers) {
  8. int comparisonCounter = 0;
  9. int memAccessCounter = 0;
  10. static int returnCounters[2];
  11. QuickSortRecurse(numbers, 0, numbers->size() - 1, &comparisonCounter, &memAccessCounter);
  12. returnCounters[0] = comparisonCounter;
  13. returnCounters[1] = memAccessCounter;
  14. return returnCounters;
  15. }
  16. void QuickSortRecurse(std::vector<int>* numbers, int i, int k, int *comparisonCounter, int *memAccessCounter) {
  17. int j = 0;
  18. /* Base case: If there are 1 or zero elements to sort,
  19. partition is already sorted */
  20. if (i >= k) {
  21. return;
  22. }
  23. /* Partition the data within the array. Value j returned
  24. from partitioning is location of last element in low partition. */
  25. j = Partition(numbers, i, k, comparisonCounter, memAccessCounter);
  26. /* Recursively sort low partition (i to j) and
  27. high partition (j + 1 to k) */
  28. QuickSortRecurse(numbers, i, j, comparisonCounter, memAccessCounter);
  29. QuickSortRecurse(numbers, j + 1, k, comparisonCounter, memAccessCounter);
  30. return;
  31. }
  32. int Partition(std::vector<int>* numbers, int i, int k, int *comparisonCounter, int *memAccessCounter) {
  33. int l = 0;
  34. int h = 0;
  35. int midpoint = 0;
  36. int pivot = 0;
  37. int temp = 0;
  38. bool done = false;
  39. /* Pick middle element as pivot */
  40. midpoint = i + (k - i) / 2;
  41. pivot = (*numbers)[midpoint];
  42. *memAccessCounter = *memAccessCounter + 1;
  43. l = i;
  44. h = k;
  45. while (!done) {
  46. /* Increment l while numbers[l] < pivot */
  47. while ((*numbers)[l] < pivot) {
  48. *comparisonCounter = *comparisonCounter + 1;
  49. *memAccessCounter = *memAccessCounter + 1;
  50. ++l;
  51. }
  52. // count the last loop's comparisons
  53. *comparisonCounter = *comparisonCounter + 1;
  54. *memAccessCounter = *memAccessCounter + 1;
  55. /* Decrement h while pivot < numbers[h] */
  56. while (pivot < (*numbers)[h]) {
  57. *comparisonCounter = *comparisonCounter + 1;
  58. *memAccessCounter = *memAccessCounter + 1;
  59. --h;
  60. }
  61. // count the last loop's comparisons
  62. *comparisonCounter = *comparisonCounter + 1;
  63. *memAccessCounter = *memAccessCounter + 1;
  64. /* If there are zero or one elements remaining,
  65. all numbers are partitioned. Return h */
  66. if (l >= h) {
  67. done = true;
  68. }
  69. else {
  70. /* Swap numbers[l] and numbers[h],
  71. update l and h */
  72. temp = (*numbers)[l];
  73. *memAccessCounter = *memAccessCounter + 1;
  74. (*numbers)[l] = (*numbers)[h];
  75. *memAccessCounter = *memAccessCounter + 2;
  76. (*numbers)[h] = temp;
  77. *memAccessCounter = *memAccessCounter + 1;
  78. ++l;
  79. --h;
  80. }
  81. }
  82. return h;
  83. }