mergesort.cpp 3.1 KB

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