代码实现:
main.cpp:
#include <iostream> #include "SortTestHelper.h" #include "MergeSort.h" using namespace std; template <typename T> void mergeSortBU(T arr[], int n){ // for( int sz = 1; sz <= n ; sz += sz ) // for( int i = 0 ; i < n ; i += sz+sz ) // // 对 arr[i...i+sz-1] 和 arr[i+sz...i+2*sz-1] 进行归并 // __merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) ); // Merge Sort Bottom Up 优化 for( int i = 0 ; i < n ; i += 16 ) insertionSort(arr,i,min(i+15,n-1)); for( int sz = 16; sz <= n ; sz += sz ) for( int i = 0 ; i < n - sz ; i += sz+sz ) if( arr[i+sz-1] > arr[i+sz] ) __merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) ); } int main() { int n = 1000000; cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl; int* arr1 = SortTestHelper::generateRandomArray(n,0,n); int* arr2 = SortTestHelper::copyIntArray(arr1, n); SortTestHelper::testSort("Merge Sort", mergeSort, arr1, n); SortTestHelper::testSort("Merge Sort Bottom Up", mergeSortBU, arr2, n); delete(arr1); delete(arr2); cout<<endl; // 测试2 测试近乎有序的数组 int swapTimes = 100; cout<<"Test for Random Nearly Ordered Array, size = "<<n<<", swap time = "<<swapTimes<<endl; arr1 = SortTestHelper::generateNearlyOrderedArray(n,swapTimes); arr2 = SortTestHelper::copyIntArray(arr1, n); SortTestHelper::testSort("Merge Sort", mergeSort, arr1, n); SortTestHelper::testSort("Merge Sort Bottom Up", mergeSortBU, arr2, n); delete(arr1); delete(arr2); return 0; }SortTestHelper.h:
#ifndef INC_04_MERGE_SORT_BOTTOM_UP_SORTTESTHELPER_H #define INC_04_MERGE_SORT_BOTTOM_UP_SORTTESTHELPER_H #include <iostream> #include <algorithm> #include <string> #include <ctime> #include <cassert> using namespace std; namespace SortTestHelper { int *generateRandomArray(int n, int range_l, int range_r) { int *arr = new int[n]; srand(time(NULL)); for (int i = 0; i < n; i++) arr[i] = rand() % (range_r - range_l + 1) + range_l; return arr; } int *generateNearlyOrderedArray(int n, int swapTimes){ int *arr = new int[n]; for(int i = 0 ; i < n ; i ++ ) arr[i] = i; srand(time(NULL)); for( int i = 0 ; i < swapTimes ; i ++ ){ int posx = rand()%n; int posy = rand()%n; swap( arr[posx] , arr[posy] ); } return arr; } int *copyIntArray(int a[], int n){ int *arr = new int[n]; copy(a, a+n, arr); return arr; } template<typename T> void printArray(T arr[], int n) { for (int i = 0; i < n; i++) cout << arr[i] << " "; cout << endl; return; } template<typename T> bool isSorted(T arr[], int n) { for (int i = 0; i < n - 1; i++) if (arr[i] > arr[i + 1]) return false; return true; } template<typename T> void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) { clock_t startTime = clock(); sort(arr, n); clock_t endTime = clock(); cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl; assert(isSorted(arr, n)); return; } }; #endifMergeSort.h:
#ifndef INC_04_MERGE_SORT_BOTTOM_UP_MERGESORT_H #define INC_04_MERGE_SORT_BOTTOM_UP_MERGESORT_H #include <iostream> #include <algorithm> #include "InsertionSort.h" using namespace std; template<typename T> void __merge(T arr[], int l, int mid, int r){ T aux[r-l+1]; for( int i = l ; i <= r; i ++ ) aux[i-l] = arr[i]; int i = l, j = mid+1; for( int k = l ; k <= r; k ++ ){ if( i > mid ) { arr[k] = aux[j-l]; j ++;} else if( j > r ){ arr[k] = aux[i-l]; i ++;} else if( aux[i-l] < aux[j-l] ){ arr[k] = aux[i-l]; i ++;} else { arr[k] = aux[j-l]; j ++;} } } template<typename T> void __mergeSort(T arr[], int l, int r){ if( r - l <= 15 ){ insertionSort(arr, l, r); return; } int mid = (l+r)/2; __mergeSort(arr, l, mid); __mergeSort(arr, mid+1, r); if( arr[mid] > arr[mid+1] ) __merge(arr, l, mid, r); } template<typename T> void mergeSort(T arr[], int n){ __mergeSort( arr , 0 , n-1 ); } #endif //INC_04_MERGE_SORT_BOTTOM_UP_MERGESORT_HinsertionSort.h:
#ifndef INC_04_MERGE_SORT_BOTTOM_UP_INSERTIONSORT_H #define INC_04_MERGE_SORT_BOTTOM_UP_INSERTIONSORT_H #include <iostream> #include <algorithm> using namespace std; template<typename T> void insertionSort(T arr[], int n){ for( int i = 1 ; i < n ; i ++ ) { T e = arr[i]; int j; for (j = i; j > 0 && arr[j-1] > e; j--) arr[j] = arr[j-1]; arr[j] = e; } return; } // 对arr[l...r]范围的数组进行插入排序 template<typename T> void insertionSort(T arr[], int l, int r){ for( int i = l+1 ; i <= r ; i ++ ) { T e = arr[i]; int j; for (j = i; j > l && arr[j-1] > e; j--) arr[j] = arr[j-1]; arr[j] = e; } return; } #endif //INC_04_MERGE_SORT_BOTTOM_UP_INSERTIONSORT_H