zoukankan      html  css  js  c++  java
  • 归并排序 总结

    前言

          归并排序(Merge Sort)是利用“归并”技术来进行排序。归并是指将若干个已排序的子文件合并成一个有序的文件。

    一、两路归并排序算法

    1、算法基本思路

    设两个有序的子文件(相当于输入堆)放在同一向量中相邻的位置上:R[low..m],R[m+1…high],先将它们合并到一个局部的暂存向量R1(相当于输出堆)中,待合并完成后将R1复制回R[low…high]中。

    2、两路归并排序算法核心

    归并排序的算法思想是分而治之(divide-conquer),每个递归过程分为三个步骤:

    1)分解:把待排序的n个元素的序列分解成两个子序列,每个子序列包括n/2个元素;

    2)治理:对每个子序列分别调用归并排序(MergeSort),进行归并操作;

    3)合并:合并两个排好序的子序列,生成排序结果。

    3、两路归并排序的示例

       归并排序是一个基于分治法的比较排序算法。目前看来还不错,那么当我们有一个非常大的列表需要排序。显然,如果我们将列表分成两个子列表,然后排序他们会更好些。如果等分以后还是太大,那就继续分割,知道我们可以很简单排序为止,如下图。。

                image

    上图描述了在算法中的某些步骤,我们已经得到两个排好序的列表,接着要做的就是巧妙地合并它们。然而,这也不是特别难。我们可以比较两个列表的第一个元素,将其中较小的元素取出放在一个新的列表中(这样得到的列表一定是有序的列表)。

    4、两路归并排序算法的实现

    /** 
    
        功能:归并排序
    
        用分治法对arr[low..high]进行二路归并排序
    
    */
    
    void MergeSort(int arr[],int low, int high)
    
    {
    
        int mid;
    
        if (low<high)    // 保证区间长度大于1
    
        {
    
            mid = (low+high)/2;        // 分解
    
            MergeSort(arr,low,mid);     // 递归地对arr[low..mid]排序
    
            MergeSort(arr,mid+1,high);  // 递归地对arr[mid+1...high]排序
    
            Merge(arr,low,mid,high);    // 组合,将两个有序区归并为一个有序区
    
        }
    
    }
    /** 
    
        功能:合并两个序列,组成新的一个有序序列
    
        思路:
    
              1、使用临时序列始终保持两个序列中最小的值
    
              2、将临时序列的值赋给组合的这个序列
    
    */
    
    void Merge(int arr[], int start, int mid, int end)
    
    {
    
        int i,j,m,n;     // 记录两个区间的起始于结束位置
    
        int k;            // 为临时存储这两个区间的开始位置
    
        int *temp;        // 临时存储合并两个区间的值
    
        i = start; j = mid + 1;    // 两个区间的起始位置
    
        m = mid;    n = end;       // 两个区间的结束位置
    
        k = 0; temp = NULL;
    
        temp = new int[end-start+1];
    
        if (NULL == temp)
    
        {
    
            cout << "内存分配失败!" << endl;
    
            exit(-1);
    
        }
    
        while (i<=m && j<=n)            // 存储两个区间公共长度的最小值
    
        {
    
            if (arr[i]<=arr[j])
    
            {
    
                temp[k++] = arr[i++];
    
            }
    
            else
    
                temp[k++] = arr[j++];
    
        }
    
        while (i<=m)                    // 存储第一个区间剩下的最小值(如果还剩下的话)
    
        {
    
            temp[k++] = arr[i++];
    
        }
    
        while (j<=n)                    // 存储第二个区间剩下的最小值(如果还剩下的话)
    
        {
    
            temp[k++] = arr[j++];
    
        }
    
        for (i=0; i<k; i++)                // 将临时存储的值重新赋给输入数组
    
        {
    
            arr[start+i] = temp[i];        // start的值不一定是0,因此在赋值时不能省略
    
        }
    
        delete []temp;                    // 释放内存
    
        temp = NULL;
    
    }  

    5、归并排序算法的性能分析

           归并排序是一种稳定的排序,对于长度为n的文件,需进行趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。

          归并排序需要一个辅助向量来暂存两个有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。

  • 相关阅读:
    Go组件学习——Web框架Gin
    一次线上接口超时的排查过程
    Go组件学习——手写连接池并没有那么简单
    终于跑通分布式事务框架tcc-transaction的示例项目
    Go语言学习——如何实现一个过滤器
    Go组件学习——database/sql数据库连接池你用对了吗
    我们这一年 | 诗人呀
    NodeMan架构
    NodeMan介绍
    微信小程序录音实现
  • 原文地址:https://www.cnblogs.com/aoguren/p/3293202.html
Copyright © 2011-2022 走看看