算法分析与设计:归并排序

归并(合并)排序(Merge Sort)

  • 基于分治策略
  • 核心思想:就是把数组分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排序好的子集合合并。

递归法

// 归并排序递归框架
int tmpArray[];
void MergeSort(int array[], int left, int right)
{
    if (left < right) // 至少两个元素
    {
        int i = (left + right) / 2; // 取中点
        MergeSort(array, left, i);
        MergeSort(array, i + 1, right);
        Merge(array, tmpArray, left, i, right); // 合并到数组tmpArray
        Copy(array, tmpArray, left, right);     // 将tmpArray中的数据复制回array
    }
}

其中,算法 Merge 合并两个排好序的数组到一个新的数组 tmpArray 中,然后由 Copy 将合并后的数组再复制回 array 中。 MergeCopy 操作都是在 O ( n ) O(n) O(n) 时间内完成的,因此归并排序算法对 n n n 个元素排序的时间复杂度为:
T ( n ) = { O ( 1 ) n ⩽ 1 2 T ( n / 2 ) + O ( n ) n > 1 T(n)=\left\{\begin{array}{ll} O(1) & n \leqslant 1 \\ 2T(n/2)+O(n) & n>1 \end{array}\right. T(n)={O(1)2T(n/2)+O(n)n1n>1
解得: T ( n ) = O ( n log ⁡ n ) T(n)=O(n\log n) T(n)=O(nlogn)


非递归法

int *MergeSort(int array[], int len)
{
    int *a = array;
    int *b = new int[len];
    // 每次循环的规模(seg)翻倍
    for (int seg = 1; seg < len; seg += seg)
    {
        for (int start = 0; start < len; start += seg + seg)
        {
            int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
            int k = low;
            int start1 = low, end1 = mid;
            int start2 = mid, end2 = high;
            while (start1 < end1 && start2 < end2) // 合并两个数组
                b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
            while (start1 < end1) // 数组2已经合并完了,开始合并剩余的数组1
                b[k++] = a[start1++];
            while (start2 < end2) // 数组1已经合并完了,开始合并剩余的数组2
                b[k++] = a[start2++];
        }
        int *temp = a;
        a = b;
        b = temp;
    }
    if (a != array)
    {
        for (int i = 0; i < len; i++)
            b[i] = a[i];
        b = a;
    }
    return b;
}

使用循环的方法,就是先将待排序数组中的相邻元素两两配对,然后按照大小进行两两合并,每次合并的规模增加一倍。


如果想了解其他排序算法可见:算法分析与设计:7大排序算法大汇总(C++)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值