归并排序法 - Merge Sort

简单记录 - 玩转算法系列–玩转算法 -高级排序算法(Sorting-Advance)

O(n*log n)的排序算法 归并排序法 - Merge Sort

nlogn 比 n^2 快多少?



测试用例太少了 优势 数据量

nlogn 的算法,n逐渐增大,速度优势越来越明显。

一个优化改进后的算法也许是一个笨的算法一辈子都赶不上的结果,好的优化后算法一瞬间就运算完了。

归并排序设计思想

归并排序算法会把序列分成长度相同的两个子序列,当无法继续往下分时(也就是每个子序列中只有一个数据时),就对子序列进行归并。归并指的是把两个排好序的子序列合并成一个有序序列。该操作会一直重复执行,直到所有子序列都归并为一个整体为止。

时间、空间复杂度

归并排序

执行时间:平均情况与最差情况为O(nlog(n)),

归并排序中,分割序列所花费的时间不算在运行时间内(可以当作序列本来就是分割好的)。在合并两个已排好序的子序列时,只需重复比较首位数据的大小,然后移动较小的数据,因此只需花费和两个子序列的长度相应的运行时间。也就是说,完成一行归并所需的运行时间取决于这一行的数据量。看一下上面的图便能得知,无论哪一行都是n个数据,所以每行的运行时间都为O(n)。而将长度为n的序列对半分割直到只有一个数据为止时,可以分成log2n行,因此,总共有log2n行。也就是说,总的运行时间为O(nlogn)。

存储空间:看情况。一般是归并排序的空间复杂度是O(n),因为归并时用到了辅助数组。

归并排序是将数组分成两半,这两半分别排序后,再归并在一起。排序某一半时,继续沿用同样的排序算法,最终,将归并两个只含一个元素的数组。这个算法的重点在于“归并”。

快速排序

执行时间:平均情况为O(nlog(n)),最差情况为O(n2),

存储空间:O(log(n))快速排序指随机挑选一个元素,对数组进行分割,以将所有比它小的元素排在比它大的元素前面。

快速排序在一般情况下,一致认为快速排序是最好的一种排序算法,而且不需要额外的存储空间。其最佳应用场合是应用于大型数据集。

我们知道归并排序的时间复杂度是O(nlogn),比最直观的O(n2)要快,但同时归并排序需要一个长度为n的辅助数组,相当于我们用O(n)的空间消耗换来了时间效率的提升,因此这是一种用空间换时间的算法。尽管归并排序可以使用手摇算法将额外空间复杂度降至 O(1),但这样最差情况下的时间复杂度会因此上升至O(N2)。

归并排序基本上与快速排序算法的性能相同,但它需要使用两倍于快速排序的存储空间,而具有讽刺意味的是,其最佳应用场合是在超大数据集中,因为归并排序的原理就是对原始的乱序数据不断进行对半分割。

归并排序图解

Merge Sort

归并排序

归并基本思想是将两个(或以上)有序的序列合并成一个新的有序序列。细化来说,归并排序先将长度为n的无序序列看成是n个长度为1的有序子序列,首先做两两合并,得到 n/2个长度为2的有序子序列,再做两两合并……不断地重复这个过程,最终可以得到一个长度为n的有序序列。

整个序列一直划分,直到无法继续往下分时(也就是每个子序列中只有一个数据时),就对子序列进行归并。

O(n*log n)

O(n) O(logn)

每一部分就一个元素了 。为什么分到只有一个呢?不用排序了 ,简单归并。

例如:长度为8的数据序列,只需经过3次合并。也就是说,对于长度为n的数据序列,只需经过log2n次合并。对于归并排序而言,其算法关键就在“合并”。如何将两个有序的数据序列合并成一个新的有序序列?合并算法的具体步骤如下。

左右分别排序 分半 排序 归并

8 6 2 3 1 5 7 4

6 8 2 3 1 5 4 7

归并过程Merge



辅助我们 临时空间 存储序列

多使用了存储空间 O(n)

时间、空间 一般优先考虑时间

三个索引 i j k

最后序列 1 2 3 4 5 6 7 8

归并过程 一部分与另一部分比较 一个个比 小到大 小就放过去

递归 归并排序

归并排序描述

像快速排序算法一样,由于归并排序也是一种分治算法,因此可以用分治法的思想将排序分为三个步骤,这样有助理解:

1.分:将数据集等分为两半。

2.治:分别在两个部分用递归的方式继续使用归并排序法。

3.合:将分开的两个部分合并成一个有序的数据集。

归并排序与其他排序最大的不同在于它的归并过程。这个过程就是将两个有序的数据集合并成一个有序的数据集。正如我们看到的,合并两个有序数据集的过程是高效的,因为我们只需要遍历一次即可。根据以上事实,再加上该算法是按照可预期的方式来划分数据的,这使得归并排序在所有的情况下都能达到快速排序的平均性能。遗憾的是,归并排序需要额外的存储空间来运行,这也是它的一个缺点。因为合并过程不能在无序数据集本身中进行,所以必须要有两倍于无序数据集的空间来运行算法。这点不足极大地降低实际中使用归并排序的频率,因为通常可以使用不需要额外存储空间的快速排序来代替它。然而,归并排序对于海量数据处理还是非常有价值的,因为它能够按预期将数据集分开。这使得我们能够将数据集分割为更加可管理的数据,接着用归并排序将处理数据,然后不断地合并数据,在这个过程中并不需要一次存储所有的数据。

归并排序小结

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。归并排序算法会把序列分成长度相同的两个子序列,当无法继续往下分时(也就是每个子序列中只有一个数据时),就对子序列进行归并。归并指的是把两个排好序的子序列合并成一个有序序列。该操作会一直重复执行,直到所有子序列都归并为一个整体为止。

归并排序执行时间:平均情况与最差情况为O(nlog(n)),存储空间:看情况。一般是归并排序的空间复杂度是O(n),因为归并时用到了辅助数组。

快速排序在一般情况下,一致认为快速排序是最好的一种排序算法,而且不需要额外的存储空间。归并排序与快速排序一样,它依赖于元素之间的比较来排序,归并排序在所有的情况下都能达到快速排序的平均性能。但是,归并排序需要额外的存储空间来完成排序过程。

参考资料

1、算法精解:C语言描述作者:【美】劳顿(Loudon,K.)

2、我的第一本算法书作者:[日]宫崎修一,石田保辉

3、玩转算法系列–玩转算法 -高级排序算法

【高级排序算法】1、归并排序法 - Merge Sort的更多相关文章

  1. 【DS】排序算法之归并排序(Merge Sort)

    一.算法思想 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法的一个非常典型的应用,指的是将两个已经排序的序列合并成一个序列的操作.其归并思想如下: 1)申请空间,使其大小为两个已经 ...

  2. 排序算法:归并排序(Merge Sort)

    归并排序 归并排序采用了分治策略(divide-and-conquer),就是将原问题分解为一些规模较小的相似子问题,然后递归解决这些子问题,最后合并其结果作为原问题的解. 归并排序将排序数组A[1. ...

  3. javascript数据结构与算法--高级排序算法(快速排序法,希尔排序法)

    javascript数据结构与算法--高级排序算法(快速排序法,希尔排序法) 一.快速排序算法 /* * 这个函数首先检查数组的长度是否为0.如果是,那么这个数组就不需要任何排序,函数直接返回. * ...

  4. 【算法】归并排序(Merge Sort)(五)

    归并排序(Merge Sort) 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序 ...

  5. 【高级排序算法】2、归并排序法的实现-Merge Sort

    简单记录 - bobo老师的玩转算法系列–玩转算法 -高级排序算法 Merge Sort 归并排序 Java实现归并排序 SortTestHelper 排序测试辅助类 package algo; im ...

  6. [算法]——归并排序(Merge Sort)

    归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...

  7. Java常见排序算法之归并排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  8. javascript数据结构与算法--高级排序算法

    javascript数据结构与算法--高级排序算法 高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法-- ...

  9. javascript高级排序算法之快速排序(快排)

    javascript高级排序算法之快速排序(快排)我们之前讨论了javascript基本排序算法 冒泡排序 选择排序 插入排序 简单复习: 冒泡排序: 比较相邻的两个元素,如果前一个比后一个大,则交换 ...

随机推荐

  1. mysql 8.0忘记root密码

    1.修改参数文件添加以下内容 skip-grant-tables 2.关闭数据库 [root@node01 ~]# /etc/init.d/mysqld8 stop Shutting down MyS ...

  2. JavaSE20-线程&同步

    1.线程 1.1 基本概念 线程的概念 线程(Thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并 ...

  3. HTTPS和HTTP的那些事

    随着信息安全变得越来越重要,在浏览器.搜索引擎.CA机构.大型互联网企业的共同促进下,互联网迎来了"HTTPS加密时代".HTTPS在HTTP上建立了SSL加密层,是HTTP协议的 ...

  4. .NET Core集成CorrelationId实现全链路日志输出

    .NET Core集成CorrelationId实现全链路日志输出 一,链路追踪 随着微服务架构的流行,一次请求会涉及多个服务的调用,并且服务本身也可能会依赖其他服务,整个请求路径会构成一个调用链,当 ...

  5. Spring Cloud Alibaba (一): SpringCloud与SpringBoot版本选型

    前言   近年SpringCloud与SpringBoot更新迭代非常频繁,导致我们对两者的版本选型非常的困难.若是版本选择有问题, 会导致开发中调试兼容性占用非常多的得必要时间. SpringClo ...

  6. vue 事件基本用法

    事件基本用法 事件的函数都定义在VUE实例中的methods中,当然也可以直接写在元素内,但是这并不利于后期的维护,需要注意的是:在methods定义的函数内想要引用插值内容,需要使用this,不然就 ...

  7. js下 Day08、DOM案例

    一.摇一摇 效果图:

  8. Open SSH CVE-2020-15778

    Open SSH OpenSSH 是用于使用 SSH 协议进行远程登录的一个开源实现.通过对交互的流量进行加密防止窃听,连接劫持以及其他攻击.OpenSSH 由 OpenBSD 项目的一些开发人员开发 ...

  9. python 批量压缩手机视频

    先安装ffmpeg pip install ffmpeg-python -i https://pypi.tuna.tsinghua.edu.cn/simple 下面是代码,新建video_compre ...

  10. App性能测试揭秘(Android篇)

    阿里云 云原生应用研发平台EMAS 李嘉华(千瞬) 简介: 性能测试在移动测试领域一直是一个大难题,它最直观的表现是用户在前台使用 App 时的主观体验,然而决定体验优劣的背后,涉及到了许许多多的技术 ...