美文网首页
常见排序算法(5)--归并排序(递归版)

常见排序算法(5)--归并排序(递归版)

作者: Jack_deng | 来源:发表于2019-05-18 14:39 被阅读0次

基本思想

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

分而治之

可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。分阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

合并相邻有序子序列

再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。


"治" 代码实现

图看完了,现在来看代码吧。

void merge(int *arr, int left, int mid, int right ,int *temp)
{
    int i = left;//左序列指针
    int j = mid+1;//右序列指针
    int t = 0;//临时数组指针

    while (( i <= mid) && ( j <= right))
    {
        if (arr[i] < arr[j])
        {
            temp[t++] = arr[i++];
        }
        else
        {
            temp[t++] = arr[j++];
        }
    }
    while (i <= mid)//将左边剩余元素填充进temp中
    {
        temp[t++] = arr[i++];
    }
    while (j <= right)//将右序列剩余元素填充进temp中
    {
        temp[t++] = arr[j++];
    }
    t = 0;
    //将temp中的元素全部拷贝到原数组中
    while (left <= right)
    {
        arr[left++] = temp[t++];
    }
}

这个函数有点难理解,我们还是拿上图的具体例子来说吧。执行merge(arr, 0, 4, 8, temp),其实就是把{4,5,7,8}(暂时称为左子数组)和{1,2,3,6}(右子数组)两个已经有序的子序列,合并为最终序列{1,2,3,4,5,6,7,8}。先比较左右子数组的第一个元素的大小,把较小的存到临时数组的第一个元素,然后把对应的子数组的指针加1,继续比较。直到左右子数组中某一个子数组完全被复制到了temp中,接下来的while循环做的事情就是把剩下的子数组中的剩余元素都复制进temp。由于不知道是左子数组还是右子数组剩余元素,所以都要写一遍。最后把temp数组的元素拷贝到arr中,arr就排序好了。

"分" 代码实现
void MSort(int *arr, int left, int right, int *temp)
{
    // if (left = right) return; 
    if (left < right)
    {
        int mid = (left + right) / 2;
        MSort(arr, left, mid, temp);//左边归并排序,使得左子序列有序
        MSort(arr, mid+1, right, temp);//右边归并排序,使得右子序列有序
        merge(arr, left, mid, right, temp);//将两个有序子数组合并操作
    }
}

"分"采用了递归的方法,采用了折半的策略,先归并左子数组,再归并右子数组,再把左右子数组合并。有的读者可能觉得MSort函数没有终止条件,其实它是有的,隐含的条件是这个if (left = right) return;,因为当left = right时,其实只有一个元素,肯定是有序的。

归并排序递归版 代码实现
// 归并排序递归版
void MergeSort(int *arr, int length)
{
    int *temp = (int *)malloc(sizeof(int) * length);//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
    MSort(arr, 0, length-1, temp);
    free(temp);
}

归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。

相关文章

  • 三大排序算法

    归并排序[稳定的排序算法] 递归实现 非递归实现 快速排序[不稳定的排序算法] 堆排序[不稳定的排序算法]

  • 常见排序算法(5)--归并排序(递归版)

    基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-an...

  • LeetCode大全

    1.常见排序算法: 常见的排序算法:冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序、计数排序、...

  • 排序

    八大排序算法 一、归并排序 递归及非递归的JAVA实现 二、快速排序 快排算法JAVA实现 三、堆排序 堆排序堆排...

  • Python知识点:常见算法的python实现

    提到排序算法,常见的有如下几种:冒泡排序、选择排序、插入排序、快速排序、堆排序、归并排序、希尔排序;查找算法最常见...

  • 归并排序基本知识介绍

    前言 归并排序稍微有那么些些的麻烦,归并排序中会涉及到递归算法。归并排序是建立在归并操作上的一种有效的排序算法。该...

  • python笔试面试项目实战2020百练6归并排序快速排序

    归并排序 现在,我们将注意⼒转向使⽤分治策略改进排序算法。要研究的第⼀个算法是归并排序 ,它是递归算法,每次将⼀个...

  • 算法汇总

    关于算法: 基础技巧:分治、二分、贪心排序算法:快速排序、归并排序、计数排序搜索算法:回溯、递归、深度优先遍历,广...

  • 排序算法

    常见的排序算法 常见的排序算法有:插入、希尔、选择、冒泡、归并、快速、堆排序。。。 插入排序 算法步骤一、从数组的...

  • 常见排序算法

    这里介绍四种排序算法,选择排序、快速排序、归并排序、计数排序 选择排序(使用递归) 选择排序(使用循环) 快速排序...

网友评论

      本文标题:常见排序算法(5)--归并排序(递归版)

      本文链接:https://www.haomeiwen.com/subject/mvanaqtx.html