mergesort.cpp 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Merge Sort
  2. //
  3. // Author: Rob Gysel
  4. // ECS60, UC Davis
  5. // Adapted from: Lysecky & Vahid "Data Structures Essentials", zyBooks
  6. #include "mergesort.h"
  7. #include <iostream>
  8. #include <cstdio>
  9. int* MergeSort(std::vector<int>* numbers) {
  10. int comparisonCounter = 0;
  11. int memAccessCounter = 0;
  12. static int returnCounters[2];
  13. MergeSortRecurse(numbers, 0, numbers->size() - 1, &comparisonCounter, &memAccessCounter);
  14. memAccessCounter++;
  15. returnCounters[0] = comparisonCounter;
  16. returnCounters[1] = memAccessCounter;
  17. return returnCounters;
  18. }
  19. void MergeSortRecurse(std::vector<int>* numbers, int i, int k, int *comparisonCounter, int *memAccessCounter) {
  20. int j = 0;
  21. if (i < k) {
  22. j = (i + k) / 2; // Find the midpoint in the partition
  23. // Recursively sort left and right partitions
  24. MergeSortRecurse(numbers, i, j, comparisonCounter, memAccessCounter);
  25. *memAccessCounter = *memAccessCounter + 1;
  26. MergeSortRecurse(numbers, j + 1, k, comparisonCounter, memAccessCounter);
  27. *memAccessCounter = *memAccessCounter + 1;
  28. // Merge left and right partition in sorted order
  29. Merge(numbers, i, j, k, comparisonCounter, memAccessCounter);
  30. *memAccessCounter = *memAccessCounter + 1;
  31. }
  32. }
  33. void Merge(std::vector<int>* numbers, int i, int j, int k, int *comparisonCounter, int *memAccessCounter) {
  34. int mergedSize = k - i + 1; // Size of merged partition
  35. int mergePos = 0; // Position to insert merged number
  36. int leftPos = 0; // Position of elements in left partition
  37. int rightPos = 0; // Position of elements in right partition
  38. std::vector<int> mergedNumbers;
  39. mergedNumbers.resize(mergedSize); // Dynamically allocates temporary array
  40. // for merged numbers
  41. leftPos = i; // Initialize left partition position
  42. rightPos = j + 1; // Initialize right partition position
  43. // Add smallest element from left or right partition to merged numbers
  44. while (leftPos <= j && rightPos <= k) {
  45. if ((*numbers)[leftPos] < (*numbers)[rightPos]) {
  46. *comparisonCounter = *comparisonCounter + 1;
  47. *memAccessCounter = *memAccessCounter + 2;
  48. mergedNumbers[mergePos] = (*numbers)[leftPos];
  49. *memAccessCounter = *memAccessCounter + 1;
  50. ++leftPos;
  51. }
  52. else {
  53. mergedNumbers[mergePos] = (*numbers)[rightPos];
  54. *memAccessCounter = *memAccessCounter + 1;
  55. ++rightPos;
  56. }
  57. ++mergePos;
  58. }
  59. // If left partition is not empty, add remaining elements to merged numbers
  60. while (leftPos <= j) {
  61. mergedNumbers[mergePos] = (*numbers)[leftPos];
  62. *memAccessCounter = *memAccessCounter + 1;
  63. ++leftPos;
  64. ++mergePos;
  65. }
  66. // If right partition is not empty, add remaining elements to merged numbers
  67. while (rightPos <= k) {
  68. mergedNumbers[mergePos] = (*numbers)[rightPos];
  69. *memAccessCounter = *memAccessCounter + 1;
  70. ++rightPos;
  71. ++mergePos;
  72. }
  73. // Copy merge number back to numbers
  74. for (mergePos = 0; mergePos < mergedSize; ++mergePos) {
  75. (*numbers)[i + mergePos] = mergedNumbers[mergePos];
  76. *memAccessCounter = *memAccessCounter + 1;
  77. }
  78. }