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