数据结构算法学习总结-慕课网(七)归并排序优化(自顶向下,从小到大)
1.回顾
上一节讲到归并排序,了解了归并排序的基本实现
这一节将讲归并排序的两个优化
2.思路
1.归并排序最后归并的时候,左边和右边都是有序的,对于[123467]这样的数组,首先划分开左右两边,123|456,比较mid=3中间的元素和mid+1=4,划分之后右边第一个元素,发现3比4小,那么就不需要继续归并,即实现了优化
2.可以在归并过程中,混合插入排序,我们知道对于一个近乎有序的数组,插入排序的性能将会很好
3.实战(关键)
MergeSort.h
#ifndef MERGESORT_H_ #define MERGESORT_H_ #include <iostream> /** * 将[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; //优化2 if(l >= r-15){ insertSort(arr,l,r); return; } int mid = (l+r)/2; __mergeSort(arr,l,mid); __mergeSort(arr,mid+1,r); //优化1 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
部分测试代码
int main(){ int n = 100000; int* arr = SortTestHelper::generateNearlyOrderedArray(n,100); int* arr1 = SortTestHelper::copyArray(arr,n); SortTestHelper::testSort("Merge Sort:",mergeSort,arr,n); SortTestHelper::testSort("insert Sort:",insertSort,arr1,n); delete[] arr; delete[] arr1; return 0; }
运行结果
Merge Sort: : 0.003sinsert Sort: : 0.007s
总结
对于近乎有序的数组,优化后的归并排序,性能甚至比单纯的插入排序更高