归并排序总结

算法原理

归并排序是分治法的典型应用,把两个或k个有序的子序列合并为一个。2路归并,2合一。k路归并,k合一。内部排序通常采用2路归并排序,先将数组分成两半,分别排序,然后合并。合并的过程需要将两个有序的子数组合并成一个有序的数组。

递归代码实现

//A[left...mid]和A[mid+1...right]这两个部分各自有序,本函数的作用是将两个部分归并
//B是辅助数组,其元素个数和元素内容与待归并数组A相同
void Merge(int A[],int left,int mid,int right,int B[]){
    int i = left;
    int j = mid+1;
    int k = left;
    while(i <= mid && j <= right){
        if(A[i]<=A[j])//A[i]和A[j]相等的情况,把A[i]赋给B[k],确保算法稳定性
            B[k++] = A[i++];
        else
            B[k++] = A[j++];
    }
    while(i <= mid)   B[k++] = A[i++];
    while(j <= right) B[k++] = A[j++];
    //将归并后的数组B转存到A中
    for(int p = left;p <=right;p++) A[p] = B[p];
}

//对数组A的[left...right]部分归并排序
//B是辅助数组,其元素个数和元素内容与待归并数组A相同
void MergeSort(int A[],int left,int right,int B[]){
    if(left < right){
        // 当 left 和 right 的值较大时(例如接近 INT_MAX),left + right 可能导致整数溢出。
        // int mid = (left + right) /2;   
        int mid = left + (right - left)/2;//避免整数溢出
        MergeSort(A,left,mid,B);    //对左半部分归并排序
        MergeSort(A,mid+1,right,B); //对右半部分归并排序
        Merge(A,left,mid,right,B);  //归并
    }
}

 非递归(迭代)代码

Merge函数与递归代码中的一模一样。

//A[left...mid]和A[mid+1...right]这两个部分各自有序,本函数的作用是将两个部分归并
//B是辅助数组,其元素个数和元素内容与待归并数组A相同
void Merge(int A[],int left,int mid,int right,int B[]){
    int i = left;
    int j = mid+1;
    int k = left;
    while(i <= mid && j <= right){
        if(A[i]<=A[j])//A[i]和A[j]相等的情况,把A[i]赋给B[k],确保算法稳定性
            B[k++] = A[i++];
        else
            B[k++] = A[j++];
    }
    while(i <= mid)   B[k++] = A[i++];
    while(j <= right) B[k++] = A[j++];
    //将归并后的数组B转存到A中
    for(int p = left;p <=right;p++) A[p] = B[p];
}


//对数组A做归并排序,数组A中从序号0开始一共存放有n个元素
//B是辅助数组,其元素个数和元素内容与待归并数组A相同
void MergeSortNonRecursive(int A[],int n,int B[]){
    //步长从1开始,每次翻倍
    for(int step = 1;step < n;step*=2){
        for(int left = 0;left < n;left += 2*step){
            //计算当块的中间点和右边界
            int mid = left + step -1;
            int right = (left + 2*step -1 < n) ? (left + 2*step -1) : n-1;
            //如果mid>=n-1,说明没有第二个子数组,跳过合并
            if(mid >= n-1) break;
            //合并两个子数组
            Merge(A,left,mid,right,B);
        }
    }
}

总结

n个元素进行2路归并排序,归并趟数=向上取整(log2n)。

每一趟归并时间复杂度是O(n)。

算法时间复杂度是O(nlog2n)。

2路归并排序性质
时间复杂度O(nlogn)
空间复杂度O(n)大小为n的辅助数组
稳定性稳定
适用性顺序表、链表

递归版本与非递归版本的对比

特性递归版本非递归版本
代码结构更简洁需显式控制循环和边界条件
空间开销递归栈+辅助数组仅需辅助数组
适用场景代码易读性优先避免递归深度过大导致栈溢出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值