归并排序法 - 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的更多相关文章
-
【DS】排序算法之归并排序(Merge Sort)
一.算法思想 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法的一个非常典型的应用,指的是将两个已经排序的序列合并成一个序列的操作.其归并思想如下: 1)申请空间,使其大小为两个已经 ...
-
排序算法:归并排序(Merge Sort)
归并排序 归并排序采用了分治策略(divide-and-conquer),就是将原问题分解为一些规模较小的相似子问题,然后递归解决这些子问题,最后合并其结果作为原问题的解. 归并排序将排序数组A[1. ...
-
javascript数据结构与算法--高级排序算法(快速排序法,希尔排序法)
javascript数据结构与算法--高级排序算法(快速排序法,希尔排序法) 一.快速排序算法 /* * 这个函数首先检查数组的长度是否为0.如果是,那么这个数组就不需要任何排序,函数直接返回. * ...
-
【高级排序算法】2、归并排序法的实现-Merge Sort
简单记录 - bobo老师的玩转算法系列–玩转算法 -高级排序算法 Merge Sort 归并排序 Java实现归并排序 SortTestHelper 排序测试辅助类 package algo; im ...
-
[算法]——归并排序(Merge Sort)
归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlog ...
-
Java常见排序算法之归并排序
在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...
-
javascript数据结构与算法--高级排序算法
javascript数据结构与算法--高级排序算法 高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法-- ...
-
javascript高级排序算法之快速排序(快排)
javascript高级排序算法之快速排序(快排)我们之前讨论了javascript基本排序算法 冒泡排序 选择排序 插入排序 简单复习: 冒泡排序: 比较相邻的两个元素,如果前一个比后一个大,则交换 ...
-
排序算法总结(二)归并排序【Merge Sort】
一.归并排序原理(Wikipedia) 归并排序本质是分治思想的应用,并且各层分治递归可以同时进行 1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 2.设定两个指针,最初位置 ...
随机推荐
-
如何利用mono把.net windows service程序迁移到linux上
How to migrate a .NET Windows Service application to Linux using mono? 写在最前:之所以用要把windows程序迁移到Linux上 ...
-
opencv算法学习
1.改变图像的亮度和对比度: 算法介绍:对每一点像素值的r,g,b,值进行乘法和加法的运算. 代码使用: ; y < image.rows; y++ ) { ; x < image.col ...
-
两个不同的list随机组合到一个List中。
今天组长给了一个绑定任务,业务需要把一男一女随机的老师绑定到考场. 测试例子入下: package com.test; import java.util.ArrayList; import java. ...
-
xxx.app已损坏,打不开.你应该将它移到废纸篓 macOS 10.12 Sierra
出现这个问题的解决方法: 修改系统配置:系统偏好设置... -> 安全性与隐私.修改为任何来源 如果没有这个选项的话 (macOS Sierra 10.12) ,打开终端,执行 sudo spc ...
-
oracle job草稿
sa -- 声明job DECLARE job2014_12_16 NUMBER; BEGIN DBMS_JOB.SUBMIT(job2014_12_16, -- 这个参数是out类型 'syncv5 ...
-
OC学习笔记——类别(Category)
类别,有些程序员又称之为分类. 类别是一种为现有的类添加新方法的方式,尤其是为系统的做扩展的时候,不用继承系统类,可以直接为类添加新的方法.也可以覆盖系统类的方法. 如: @interface NSO ...
-
kuangbin_UnionFind B (POJ 1611)
过程是模板 merge完后扫一下几个跟0同祖先节点就是答案了 #include <iostream> #include <string> #include <cstdio ...
-
File ";/struts-tags"; not found
前言 由于在某个jsp引用了struts标签库,导致该错误产生--这是stuts项目算是一道经典错误,往往最后的解决方式是更换Tomcat.今天我记录的是引起这一错误的一个非常隐藏的原因. 错误描述 ...
-
如何解决:新建Android程序的时候发生了找不到 \android-sdk-windows\tools\lib\proguard.cfg文件 的错误
问题概述: 在新建Android程序的时候出现以下错误: 找不到 \android-sdk-windows\tools\lib\proguard.cfg文件 原因: SDK不完整. 解决方法: 方法一 ...
-
线性表顺序存储方式的C语言实现
/* 编译器VC6++ 文件名1.cpp 代码版本号:1.0 时间:2015年9月14日16:39:21 */ #include <stdio.h> #include <stdlib ...