// Merge Sort // // Author: Rob Gysel // ECS60, UC Davis // Adapted from: Lysecky & Vahid "Data Structures Essentials", zyBooks #include "mergesort.h" #include #include int* MergeSort(std::vector* numbers) { int comparisonCounter = 0; int memAccessCounter = 0; static int returnCounters[2]; MergeSortRecurse(numbers, 0, numbers->size() - 1, &comparisonCounter, &memAccessCounter); returnCounters[0] = comparisonCounter; returnCounters[1] = memAccessCounter; return returnCounters; } void MergeSortRecurse(std::vector* numbers, int i, int k, int *comparisonCounter, int *memAccessCounter) { int j = 0; if (i < k) { j = (i + k) / 2; // Find the midpoint in the partition // Recursively sort left and right partitions MergeSortRecurse(numbers, i, j, comparisonCounter, memAccessCounter); MergeSortRecurse(numbers, j + 1, k, comparisonCounter, memAccessCounter); // Merge left and right partition in sorted order Merge(numbers, i, j, k, comparisonCounter, memAccessCounter); } } void Merge(std::vector* numbers, int i, int j, int k, int *comparisonCounter, int *memAccessCounter) { int mergedSize = k - i + 1; // Size of merged partition int mergePos = 0; // Position to insert merged number int leftPos = 0; // Position of elements in left partition int rightPos = 0; // Position of elements in right partition std::vector mergedNumbers; mergedNumbers.resize(mergedSize); // Dynamically allocates temporary array // for merged numbers leftPos = i; // Initialize left partition position rightPos = j + 1; // Initialize right partition position // Add smallest element from left or right partition to merged numbers while (leftPos <= j && rightPos <= k) { *comparisonCounter = *comparisonCounter + 1; *memAccessCounter = *memAccessCounter + 2; if ((*numbers)[leftPos] < (*numbers)[rightPos]) { mergedNumbers[mergePos] = (*numbers)[leftPos]; *memAccessCounter = *memAccessCounter + 2; ++leftPos; } else { mergedNumbers[mergePos] = (*numbers)[rightPos]; *memAccessCounter = *memAccessCounter + 2; ++rightPos; } ++mergePos; } // If left partition is not empty, add remaining elements to merged numbers while (leftPos <= j) { mergedNumbers[mergePos] = (*numbers)[leftPos]; *memAccessCounter = *memAccessCounter + 2; ++leftPos; ++mergePos; } // If right partition is not empty, add remaining elements to merged numbers while (rightPos <= k) { mergedNumbers[mergePos] = (*numbers)[rightPos]; *memAccessCounter = *memAccessCounter + 2; ++rightPos; ++mergePos; } // Copy merge number back to numbers for (mergePos = 0; mergePos < mergedSize; ++mergePos) { (*numbers)[i + mergePos] = mergedNumbers[mergePos]; *memAccessCounter = *memAccessCounter + 2; } }