mergesort.cpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. void MergeSort(std::vector<int>* numbers, int *comparisonCounter, int *memAccessCounter) {
  8. MergeSortRecurse(numbers, 0, numbers->size() - 1, comparisonCounter, memAccessCounter);
  9. }
  10. void MergeSortRecurse(std::vector<int>* numbers, int i, int k, int *comparisonCounter, int *memAccessCounter) {
  11. int j = 0;
  12. if (i < k) {
  13. j = (i + k) / 2; // Find the midpoint in the partition
  14. // Recursively sort left and right partitions
  15. MergeSortRecurse(numbers, i, j, comparisonCounter, memAccessCounter);
  16. MergeSortRecurse(numbers, j + 1, k, comparisonCounter, memAccessCounter);
  17. // Merge left and right partition in sorted order
  18. Merge(numbers, i, j, k, comparisonCounter, memAccessCounter);
  19. }
  20. }
  21. void Merge(std::vector<int>* numbers, int i, int j, int k, int *comparisonCounter, int *memAccessCounter) {
  22. int mergedSize = k - i + 1; // Size of merged partition
  23. int mergePos = 0; // Position to insert merged number
  24. int leftPos = 0; // Position of elements in left partition
  25. int rightPos = 0; // Position of elements in right partition
  26. std::vector<int> mergedNumbers;
  27. mergedNumbers.resize(mergedSize); // Dynamically allocates temporary array
  28. // for merged numbers
  29. leftPos = i; // Initialize left partition position
  30. rightPos = j + 1; // Initialize right partition position
  31. // Add smallest element from left or right partition to merged numbers
  32. while (leftPos <= j && rightPos <= k) {
  33. if ((*numbers)[leftPos] < (*numbers)[rightPos]) {
  34. *comparisonCounter++;
  35. *memAccessCounter = *memAccessCounter + 2;
  36. mergedNumbers[mergePos] = (*numbers)[leftPos];
  37. *memAccessCounter++;
  38. ++leftPos;
  39. }
  40. else {
  41. mergedNumbers[mergePos] = (*numbers)[rightPos];
  42. *memAccessCounter++;
  43. ++rightPos;
  44. }
  45. ++mergePos;
  46. }
  47. // If left partition is not empty, add remaining elements to merged numbers
  48. while (leftPos <= j) {
  49. mergedNumbers[mergePos] = (*numbers)[leftPos];
  50. *memAccessCounter++;
  51. ++leftPos;
  52. ++mergePos;
  53. }
  54. // If right partition is not empty, add remaining elements to merged numbers
  55. while (rightPos <= k) {
  56. mergedNumbers[mergePos] = (*numbers)[rightPos];
  57. *memAccessCounter++;
  58. ++rightPos;
  59. ++mergePos;
  60. }
  61. // Copy merge number back to numbers
  62. for (mergePos = 0; mergePos < mergedSize; ++mergePos) {
  63. (*numbers)[i + mergePos] = mergedNumbers[mergePos];
  64. *memAccessCounter++;
  65. }
  66. }