排序算法八:归并排序

来源:互联网 发布:淘宝手机类目保证金 编辑:程序博客网 时间:2024/06/05 18:12

声明:引用请注明出处http://blog.csdn.net/finish_dream/article/details/70242486


引言

之前已经讲过排序算法系列的插入排序,交换排序,选择排序。本篇文章主要讲解归并排序。


排序相关的基本概念

  • 排序:将一组杂乱无章的数据按一定的规律顺次排列起来。

    • 数据表(data list):它是待排序对象的有限集合。
    • 排序码(key):通常对象有多个属性域,即多个数据成员组成,其中有一个属性域,可用来区分对象,作为排序依据。该域即为排序
      码,每个数据表用哪个属性域作为排序码,要视具体的应用需要而定。
  • 分类

    • 内排序:指在排序期间数据对象全部存放在内存的排序;
    • 外排序:指在排序期间全部对象个数太多,不能同时存放在内存,必须根据排序过程的要求,不断在内、外存之间移动的排序。

排序的分析

排序算法的稳定性

如果在对象序列中有两个对象r[i]和r[j] ,它们的排序码k[i]==k[j] 。如果排序前后,对象r[i]和r[j] 的相对位置不变,则称排序算法是稳定的;否则排序算法是不稳定的。

排序算法的评价

时间开销

  • 排序的时间开销可用算法执行中的数据比较次数数据移动次数来衡量。
  • 算法运行时间代价的大略估算一般都按平均情况进行估算。对于那些受对象排序码序列初始排列及对象个数影响较大的,需要按最好情况和最坏情况进行估算。

空间开销

算法执行时所需的附加存储。


归并排序

基本思想

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。

迭代法

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  4. 重复步骤3直到某一指针到达序列尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾

递归法

  1. 将序列每相邻两个数字进行归并操作,形成 floor(n/2)个序列,排序后每个序列包含两个元素
  2. 将上述序列再次归并,形成 floor(n/4)个序列,每个序列包含四个元素
  3. 重复步骤2,直到所有元素排序完毕

C#代码

    /// <summary>    /// 归并排序方法    /// </summary>    /// <param name="list">待排序链表</param>    /// <returns></returns>    public static List<int> Sort(List<int> list)    {        if (list.Count <= 1)        {            return list;        }        int mid = list.Count / 2;        List<int> left = new List<int>();//定义左侧List        List<int> right = new List<int>();//定义右侧List        //以下两个循环把lst分为左右两个List        for (int i = 0; i < mid; i++)        {            left.Add(list[i]);        }        for (int j = mid; j < list.Count; j++)        {            right.Add(list[j]);        }        left = Sort(left);        right = Sort(right);        return Merge(left, right);    }    /// <summary>    /// 合并两个已经排好序的List    /// </summary>    /// <param name="left">左侧List</param>    /// <param name="right">右侧List</param>    /// <returns></returns>    private static List<int> Merge(List<int> left, List<int> right)    {        List<int> temp = new List<int>();        while (left.Count > 0 && right.Count > 0)        {            if (left[0] <= right[0])            {                temp.Add(left[0]);                left.RemoveAt(0);            }            else            {                temp.Add(right[0]);                right.RemoveAt(0);            }        }        if (left.Count > 0)        {            for (int i = 0; i < left.Count; i++)            {                temp.Add(left[i]);            }        }        if (right.Count > 0)        {            for (int i = 0; i < right.Count; i++)            {                temp.Add(right[i]);            }        }        return temp;    }}

算法分析

  • 时间复杂度 Θ(nlogn)
  • 最优时间复杂度Θ(n)
  • 平均时间复杂度Θ(nlogn)
  • 空间复杂度Θ(n)

完整代码被我放在了Github上,感兴趣的可以下下来看一下https://github.com/Finish-Dream/DSAlgorithm

0 0
原创粉丝点击