数据结构算法学习总结-慕课网(六)归并排序(从小到大)
1.回顾
上一节讲到冒泡排序,对它有了基本的认识
这一节会讲性能比较好的归并排序
2.思路
如图
首先会创建一个与原{2,3,6,8}一模一样的数组tempArray,比较i和j所在的元素,可以知道2比6小,那么2就是我们要找的第一个元素,随后i角标移动到下一个位置,即3所在的位置,然后把2赋给k所在的数组的第一个元素,k角标往后移动一位,现在第一个元素排序完毕;i移动到角标为1的位置3,现在比较3和6,发现3比6小,那么3就是我们要找的元素,把3赋值给k的第二个位置,即3所在的位置,随后i角标加1;这时候的i=1,和mid=1相等啦,则对j所在的部分进行排序,往后类似。
3.实战
MergeSort.cpp
#include <iostream> #include "SortTestHelper.h" using namespace std; /** * 将[l...mid]和[mid+1...r]两部分进行归并 */ template<typename T> void __merge(T arr[],int l,int mid,int r){ //临时空间,存贮arr的数组 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++){ //i>mid表示i所在数组已经归并完,j所在的数组没有归并完,还需要归并一次 if(i > mid){ arr[k] = aux[j-l]; j++; }else if(j > r){//j>r表示j所在数组已经归并完,i所在的数组没有归并完,还需要归并一次 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++; } } } /** * 递归使用归并排序,对arr[l...r]的范围排序 */ template<typename T> void __mergeSort(T arr[],int l,int r){ if(l >= r) return; int mid = (l+r)/2; __mergeSort(arr,l,mid); __mergeSort(arr,mid+1,r); __merge(arr,l,mid,r); } template<typename T> void mergeSort(T arr[],int n){ __mergeSort(arr,0,n-1); } int main(){ int n = 100000; int* arr = SortTestHelper::generateRandomArray(n,0,100); SortTestHelper::testSort("Merge Sort:",mergeSort,arr,n); delete[] arr; return 0; }
SortTestHelper.h
#ifndef SORTTESTHELPER_H_ #define SORTTESTHELPER_H_ #include <iostream> #include <ctime> #include <cassert> using namespace std; namespace SortTestHelper{ //生成n个元素的随机数组,每个元素的随机范围为[rangeL,rangeR] int* generateRandomArray(int n,int rangeL,int rangeR){ assert(rangeL <= rangeR); //为了程序稳定性,如果rangeL>rangeR,那么程序不会往下执行 int *arr = new int[n]; srand(time(NULL));//随机种子,需要导入ctime库 for(int i = 0;i<n;i++){ arr[i] = rand() % (rangeR - rangeL + 1) + rangeL; //自己可以动笔算一下 } return arr; } /** * 检验排序的正确性 */ template<typename T> bool isSorted(T arr[],int n){ for(int i = 0;i<n;i++){ //注意,如果i=n-2时,实际上会比较arr[n-2]和arr[n-1]的值,此时数组已经比较完毕 if(i<n-1 && arr[i]>arr[i+1]){ return false; } } return true; } /** * 测试排序所需要的时间 */ template<typename T> void testSort(string sortName,void(*sort)(T arr[],int n),T arr[],int n){ clock_t startTime = clock(); sort(arr,n); clock_t endTime = clock(); assert(isSorted(arr,n)); cout <<sortName<<" : "<< double(endTime - startTime) /CLOCKS_PER_SEC <<"s" << endl; return; } template<typename T> void printArray(T arr[],int n){ for(int i = 0;i<n;i++) cout << arr[i] << ","; //循环打印数组中的元素 cout << endl; } int* copyArray(int arr[],int n){ int* b = new int[n]; //拷贝数组参数:指针开始的位置;指针结束的位置;目标数组 copy(arr,arr+n,b); return b; } /** *生成一个近乎有序的数组 */ 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 swapX = rand()%n; int swapY = rand()%n; swap(arr[swapX],arr[swapY]); } return arr; } } #endif /* SORTTESTHELPER_H_ */
运行结果
Merge Sort: : 0.019s
总结
从运行的结果可以得知,即使是10w的测试数据量,归并排序所需要的时间依然很短,性能很高
意见与建议
如果博友有任何问题或者建议,欢迎留言讨论