转自:http://www.cnblogs.com/ayqy/p/4050452.html

 

一.归并排序的优缺点(pros and cons)

耗费心思来理解它,总要有个理由吧:

  • 归并排序的效率达到了巅峰:时间复杂度为O(nlogn),这是基于比较的排序算法所能达到的最高境界
  • 归并排序是一种稳定的算法(即在排序过程中大小相同的元素能够保持排序前的顺序,3212升序排序结果是1223,排序前后两个2的顺序不变),这一点在某些场景下至关重要
  • 归并排序是最常用的外部排序方法(当待排序的记录放在外存上,内存装不下全部数据时,归并排序仍然适用,当然归并排序同样适用于内部排序...)

缺点:

  • 归并排序需要O(n)的辅助空间,而与之效率相同的快排和堆排分别需要O(logn)和O(1)的辅助空间,在同类算法中归并排序的空间复杂度略高

P.S.本文只讨论最原始的“两路归并”,多路的与之类似

二.内部原理

首先要知道归并排序的思想是:分治法,与快速排序的思想一样

算法思想:无序 ->  部分有序  ->  整体有序

归并排序中“分”与“合”的过程是结合在一起的,即每一趟都在做“分”与“合”的工作,并不是先“分”完再“合”(“分”很简单,不就是一直二分二分直到不可再分呗,额,这么想就错了,分完就合不起来了,切记“分”与“合”是结合在一起的)

用一幅图来解释归并排序的过程就足够了:

说明:P1与P2比较,将较大(小)者装入P,然后P1或者P2右移(装了谁就移谁),最后P右移

比如要对数组a[n]做升序排序,那么具体过程如下:

  1. 申请两个长度都为n/2的辅助空间,把a数组装进去,前一半装进L,后一半装进R
  2. 按照说明中的方式做一轮比较(P从A移动到C,一趟结束)

现在想想我们做完一趟排序得到了什么?

  1. 达成了部分有序(前一半 < 后一半,对吧?)
  2. 除此之外,我们很自然的把待排序序列一分为二,为递归做好了准备

还不够清晰?那么还有几句话:

  1. 图示的过程解释了为什么需要长度为n的辅助空间
  2. 只要L和R各自内部都有序(同升序或者同降序),那么只需要再经过一趟归并,排序就完成了(仔细想想,没错吧?)
  3. 排序部分就是合并部分(还记得上面提过的那句话吗?“分”与“合”的过程是结合在一起的,千万不能分开想,否则你会发现合不起来了...)

三.实现细节

如果上面的解释还不够清晰,那么我们来举个例子,一步步分析:

假定待排序序列为a[] = {3, 2, 1, 4},那么具体过程是这样的:

P.S.如果待排序序列是奇数个怎么办?这是问题吗?无非是拆得的前一半比后一半少一个而已,单趟循环控制是由P指针来做的,不存在某个P1没有与之配对的P2可以比的问题

四.总结

归并排序多用于需要外部排序的场景,除此之外当内部排序需要保证稳定性时也采用归并排序(不要求稳定性的内部排序一般采用快排或者堆排序,前者在待排序序列基本有序时效率低,后者堆的维护是个问题)

排序算法之归并排序(Mergesort)解析的更多相关文章

  1. 排序算法THREE:归并排序MergeSort

    /** *归并排序思路:分治法思想 O(nlogn) * 把数组一分为二,二分为四 * 四和为二,二和为一 * */ /** * 归并排序主方法 *@params 待排序的数组 *@params 初始 ...

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

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

  3. 【排序算法】归并排序算法 Java实现

    归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 基本思想 可以将一组数组分成A,B两组 依次类推,当分出来的小组只有一 ...

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

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

  5. 我的Java开发学习之旅------>Java经典排序算法之归并排序

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

  6. 我的Java开发学习之旅------&gt;Java经典排序算法之归并排序

    一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是採用分治法(Divide and Conquer)的一个很典型的应用.将已有序的子序列合并,得到全然有序的序列.即先使每一个子序列 ...

  7. 排序算法——QuickSort、MergeSort、HeapSort(C++实现)

    快速排序QuickSort template <class Item> void quickSort (Item a[], int l, int r) { if (r<=l) ret ...

  8. C++编程练习(15)----“排序算法 之 归并排序“

    归并排序 归并排序(Merging Sort)的原理: 假设初始序列含有 n 个记录,则可以看成是 n 个有序的子序列,每个子序列的长度为1,然后两两归并,得到 [n/2] ([ x ] 表示不小于 ...

  9. 数据结构与算法之PHP排序算法(归并排序)

    一.基本思想 归并排序算法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,使每个子序列有序,再将已有序的子序列合并,得到完全有序的序列.该算法是采用分治法(Divid ...

随机推荐

  1. 【linux】监控磁盘情况并自动删除备份文件

    背景:我有一个备份目录/home/kzy/bakup,会每天备份一些信息.随着日子一天天的过去,这个文件夹越来越大,终于把磁盘撑满了..... 需求:当磁盘占有率超过80%时自动删除该文件夹下最老的3 ...

  2. MVC:分页改进URL

    http://localhost/?page=2     可以根据"可组合URL"创建一种更具吸引力的URL方案: http://localhost/page2     publi ...

  3. ECS Navicat for MySQL远程连接报10038的错误

    解决问题时,建议先在阿里云设置好数据库访问的白名单,把自己的IP地址填进去 问题现象 Navicat for MySQL访问远程mysql数据库,出现报错,显示“2003- Can't connect ...

  4. df -h命令卡死解决办法

    1.现象 同事突然反应说有个服务器进入/目录运行 ls  -l 无反应,同时运行df  -h也卡死了.如果你的机器有用到nfs请直接看第四大点. 2.分析 运行mount [conversant@sw ...

  5. ubuntu下安装python3及常用爬虫库命令

    爬虫常用库安装:

  6. SpringBoot与SpringCloud学习指南

    推荐一个Spring Boot的导航网站:Spring Boot 中文导航 Spring boot使用的各种示例,以最简单.最实用为标准 spring-boot-helloWorld:spring-b ...

  7. 001.DNS原理及配置格式

    一 dns简介 DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串. ...

  8. Netty源码分析之NioEventLoop(二)—NioEventLoop的启动

    上篇文章中我们对Netty中NioEventLoop创建流程与源码进行了跟踪分析.本篇文章中我们接着分析NioEventLoop的启动流程: Netty中会在服务端启动和新连接接入时通过chooser ...

  9. 2,EasyNetQ-日志记录

    EasyNetQ提供了一个IEasyNetQLogger接口: public interface IEasyNetQLogger { void DebugWrite(string format, pa ...

  10. BZOJ4161 常系数齐次线性递推

    问了数竞的毛毛搞了一番也没太明白,好在代码蛮好写先记下吧. #include<bits/stdc++.h> using namespace std; ,mod=1e9+; int n,k, ...