归并排序比较适合大规模得数据排序,借鉴了分治思想。

归并排序原理

自古以来,分久必合合久必分。

我们可以这样理解归并排序,分-分到不能分为止,然后合并。

使用递归将问题一点一点分解,最后进行合并。

分而治之 (merge_sort)

提到递推,我们使用地递推解决问题,首先要分析出递推公式、明确结束条件。

递推公式:

merge_sort(i...n)=merge( merge_sort(i...j), merge_sort(j+...n) )

结束条件:
i>=n

分久必合(merge)

将两个有序的数组进行合并,这样整个数组也就是排序好的数组了。

那么怎么进行合并呢?-- (i...j) 和 (j+1...n) 重新排序后,重新放入原来的数组 (i...n)

两组数组 [3, 8, 9, 11]   vs  [1, 2, 5, 7]

两个游标      蓝色         和       红色

 3>1,1小,1入新数组,红色游标后移一位,继续比较...

  3>2,2小,2入数组,红色游标后移一位

  3<5,3小,3入数组,蓝色游标后移一位

8>5,5小,5入数组,红色游标后移一位

8>7,7小,7入数组,红色游标后移,右侧数组全部转移完毕

当有一组数组全部转移完毕,那么剩下的一组中的全部元素依次转入到新数组中,新数组正式成为一个有顺序的数组

通过以上两点:递推公式和合并思想,我们使用代码实现一下:

1、如下图:递归方式 进行分解,然后使用合并代码进行合并。

          /// <summary>
/// 递归调用
/// </summary>
/// <param name="a">原始数组</param>
/// <param name="p">分割点</param>
/// <param name="r">结束位置</param>
public static void MergrSortInternally(int[] a, int p, int r)
{
//结束条件
if (p >= r)
return; //切割点
int q = p + (r - p) / ; //分而治之
MergrSortInternally(a, p, q); MergrSortInternally(a, q + , r); //合并 A(a, p, q) 和 A(a, q + 1, r)
Merage(a, p, q, r); }

2、我们再来看看合并逻辑

参数:原始数组,开始的地方,切割的地方,结束的地方

逻辑:两个切割数组的各自的游标

申请同样大小的临时数组

     循环比较;小的入临时,游标后移;知道有一个数组空了为止

找到剩下不为空的那个数组,将剩余元素入临时

将临时数组,找到原始数组的对应为止进行覆盖

 /// <summary>
/// 合并
/// </summary>
/// <param name="a">原始数组</param>
/// <param name="p">起始点</param>
/// <param name="q">切割点</param>
/// <param name="r">结束点</param>
public static void Merage(int[] a, int p, int q, int r)
{
// i 和 j = 两个数组的游标
int i = p;
int j = q + ; // 临时数组的游标
int k = ; // 临时数组
int[] temp = new int[r - p + ]; //最小入队,直到其中一个空空如也为止
while (i <= q && j <= r)
{
if (a[i] <= a[j])
{
temp[k] = a[i];
++k;
++i;
}
else
{
temp[k] = a[j];
++k;
++j;
}
} // 找到另一个不为空的,找到剩下的元素
int start = i;
int end = q; if (j <= r)
{
start = j;
end = r;
} // 剩余数组拷贝到临时数组 temp
while (start <= end)
{
temp[k++] = a[start++];
} // 将temp覆盖到a[p...r]
for (i = ; i <= r - p; ++i)
{
a[p + i] = temp[i];
}
}

归并排序性能分析

 Q:是不是稳定排序?

 A:是

对于这两组数组   A[p...q] 和   A[q+1...r] 来说

代码中也是这样实现的,a[i]就是左侧数组,a[j]就是右侧数组,保证相等时左侧优先入队即可。注意 等号位置。

 

Q:是否是原地排序?

 A:当然不是

因为我们在合并代码时候,申请了同样大小的内存空间。

但是对于这里的归并排序的空间复杂度又是多少呢?

虽然牵扯到了递归,但是临时变量这里会在一个函数结束后栈会释放,所以空间复杂度是O(n)

Q:时间复杂度又是多少呢?

 A:O(n log n)

我们对 n 个元素的归并排序时间记作 T(n),

分解函数分解两个子数组的时间是T(n/2)

合并函数时间复杂度是O(n)

T(1)=C;    n=1

T(n)=2*T(n/2)+ n; n>1

T(n)  =  2*T(n/2)  +  n
         = 2*(2*T(n/4) + n/2) + n = 4*T(n/4) + 2*n
         = 4*(2*T(n/8) + n/4) + 2*n = 8*T(n/8) + 3*n
         = 8*(2*T(n/16) + n/8) + 3*n = 16*T(n/16) + 4*n
    ......
    = 2^k * T(n/2^k) + k * n

T(n)  = 2^k * T(n/2^k) + k * n

当 T(n/2^k) = T(1)=> k = log2 n

即:T(n) = Cn + n log2 n  => O(n log n)

经典排序算法 — C#版本(中)的更多相关文章

  1. 经典排序算法总结与实现 ---python

    原文:http://wuchong.me/blog/2014/02/09/algorithm-sort-summary/ 经典排序算法在面试中占有很大的比重,也是基础,为了未雨绸缪,在寒假里整理并用P ...

  2. 【最全】经典排序算法(C语言)

    算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首 ...

  3. python 经典排序算法

    python 经典排序算法 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.常见的内部排序算 ...

  4. 十大经典排序算法最强总结(含JAVA代码实现)(转)

    十大经典排序算法最强总结(含JAVA代码实现)   最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在“桶排序”算法中对每 ...

  5. 十大经典排序算法最强总结(含Java、Python码实现)

    引言 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法.排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面 ...

  6. 十大经典排序算法(java实现、配图解,附源码)

    前言: 本文章主要是讲解我个人在学习Java开发环境的排序算法时做的一些准备,以及个人的心得体会,汇集成本篇文章,作为自己对排序算法理解的总结与笔记. 内容主要是关于十大经典排序算法的简介.原理.动静 ...

  7. python基础__十大经典排序算法

    用Python实现十大经典排序算法! 排序算法是<数据结构与算法>中最基本的算法之一.排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大, ...

  8. 经典排序算法 – 插入排序Insertion sort

    经典排序算法 – 插入排序Insertion sort  插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 插入排序方法分直接插入排序和折半插入排序两种, ...

  9. 经典排序算法及python实现

    今天我们来谈谈几种经典排序算法,然后用python来实现,最后通过数据来比较几个算法时间 选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据 ...

随机推荐

  1. php对接微信小程序支付

    前言:这里我就假装你已经注册了微信小程序,并且基本的配置都已经好了.注: 个人注册小程序不支持微信支付,所以我还是假装你是企业或者个体工商户的微信小程序,其他的商户号注册,二者绑定,授权,支付开通,就 ...

  2. ssh商城源码 2017.6.30

    http://www.cnblogs.com/chiangchou/p/project-ebuy.html http://www.java1234.com/vipzy.html源码视频链接

  3. Spring_boot入门(1)

    Spring boot 将很多东西都集成在一起了,搭建maven项目的时候只需要引入很少的依赖就可以实现项目的搭建. 1.搭建maven项目结构 2.引入Spring boot 依赖 直接去官网找就可 ...

  4. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十五)阶段总结

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 一 每个阶段在结尾时都会有一个阶段总结,在<SSM整合基础篇& ...

  5. Java 学习笔记 (四) Java 语句优化

    这个问题是从headfirst java看到的. 需求: 一个移动电话用的java通讯簿管理系统,要求最有效率的内存使用方法. 下面两段程序的优缺点,哪个占用内存更少. 第一段: Contact[]c ...

  6. 在线数据库表(sql语句)生成java实体类工具

    相信每个做java开发的读者,都接触过SQL建表语句,尤其是在项目开发初期,因为数据库是项目的基石. 在现代项目开发中,出现了许多ORM框架,通过简单的实体映射,即可实现与数据库的交互,然而我们最初设 ...

  7. input表单中嵌入百度地图

    在做项目开发中,常常会用到定位的操作,比如在做一些资产房产等方面的业务的时候,需要知道资产的具体位置,并将位置信息保存下来,这个时候我们可以使用form表单嵌入百度地图的方式来实现这个功能,下面请看详 ...

  8. html select 标签设置默认选中

    方法有两种. 第一种通过<select>的属性来设置选中项,此方法可以在动态语言如php在后台根据需要控制输出结果. 1 2 3 4 5 < select  id =  " ...

  9. JAVA基础第三章-类与对象、抽象类、接口

    业内经常说的一句话是不要重复造轮子,但是有时候,只有自己造一个轮子了,才会深刻明白什么样的轮子适合山路,什么样的轮子适合平地! 我将会持续更新java基础知识,欢迎关注. 往期章节: JAVA基础第一 ...

  10. SSRS报表服务随笔(rdl报表服务)-创建一个简单的报表

    这段时间一直在敲rdl报表,在国内的不这么留在,在国外的话,还是挺流行的,国内的话,这方面的资料很少很少,也踏过不少坑 先从SSRS了解起,SSRS全称 SQL Server Reporting Se ...