数据结构算法学习总结-慕课网(七)归并排序优化(自顶向下,从小到大)
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
总结
对于近乎有序的数组,优化后的归并排序,性能甚至比单纯的插入排序更高