归并排序(Merge Sort)及其优化 —— C++

时间复杂度:O(n*logn)
原理:将数组分为若干子数组,各子数组分别排序,最后归并排序
在这里插入图片描述
简化版:(将数组二分成若干组,分别进行排序,最后逐步归并)
在这里插入图片描述
代码

// 将arr[l...mid]和arr[mid+1...r]两部分进行归并
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 ++ ) //注意数据的偏移量 i-l
        aux[i-l] = arr[i];
        
    int i = l, j = mid+1;
    for( int k = l ; k <= r; k ++ ){
    
         // i 索引所指的子数组中的元素已经归并完
        // j 索引所指的子数组中的元素还没有完全归并完
        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 ++;
		}
    }
}

// 递归使用归并排序,对arr[l...r]的范围进行排序
template<typename T>
void mergeSort(T arr[], int l, int r){
    //当前处理的数据集为空
    if( l >= r )
        return;
        
    int mid = (l+r)/2;
    
    //将arr[l...mid]和arr[mid+1...r]排序
    mergeSort(arr, l, mid);
    mergeSort(arr, mid+1, r);
    //若arr[mid] <= arr[mid+1],则不用归并
    if ( arr[mid] > arr[mid+1] )
        merge(arr, l, mid, r); //将两部分归并
}

优化:(元素数据比较小时,转而使用插入排序性能更高,原因:元素数据较小时,数据近乎有序的几率比较大,此时插入排序有优势)

// 递归使用归并排序,对arr[l...r]的范围进行排序
template<typename T>
void mergeSort(T arr[], int l, int r){
    if( r - l <= 15 ){ //15 只是随机列举的,范围可视情况而定
        insertionSort(arr, l, r);
        return;
    }
    。
    。
    。
}

自底向上的归并排序

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) );
}

优化

template <typename T>
void mergeSortBU(T arr[], int n){
    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) );
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值