mergesort.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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* comparisonCounterPointer, int* memAccessCounterPointer) {
  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, comparisonCounterPointer, memAccessCounterPointer);
  24. MergeSortRecurse(numbers, j + 1, k, comparisonCounterPointer, memAccessCounterPointer);
  25. // Merge left and right partition in sorted order
  26. Merge(numbers, i, j, k, comparisonCounterPointer, memAccessCounterPointer);
  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. if ((*numbers)[leftPos] < (*numbers)[rightPos]) {
  42. *comparisonCounter++;
  43. *memAccessCounter = *memAccessCounter + 2;
  44. //std::cout << ".." << std::endl;
  45. mergedNumbers[mergePos] = (*numbers)[leftPos];
  46. *memAccessCounter++;
  47. //std::cout << "." << std::endl;
  48. ++leftPos;
  49. }
  50. else {
  51. mergedNumbers[mergePos] = (*numbers)[rightPos];
  52. *memAccessCounter++;
  53. //std::cout << "." << std::endl;
  54. ++rightPos;
  55. }
  56. ++mergePos;
  57. }
  58. // If left partition is not empty, add remaining elements to merged numbers
  59. while (leftPos <= j) {
  60. mergedNumbers[mergePos] = (*numbers)[leftPos];
  61. *memAccessCounter++;
  62. //std::cout << "." << std::endl;
  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++;
  70. //std::cout << "." << std::endl;
  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++;
  78. //std::cout << "." << std::endl;
  79. }
  80. }