讨厌算法的程序员 | 第六章 归并排序

分而治之

从算法设计的分类上来说,插入排序属于增量方法。在排序好子数组A[1 ‥ j-1]后,再将单个元素A[j]插入子数组的适当位置,产生排序好的子数组A[1 ‥ j]。整个算法就是不断以此方法增量插入,直到子数组包含了所有数组元素。

本篇将要介绍的归并排序,是用另一种思想来解决排序问题的,在算法设计分类上属于分治法。

分治法思想是,将原问题分解为几个规模较小但类似于原问题的子问题,递归的求解这些子问题,然后在合并这些子问题的解,最终建立原问题的解。

这里提到一个词递归,其解释是:为了解决一个给定问题,算法一次或多次的调用其自身以解决紧密相关的子问题。递归是分治思想的一个具体实现。

分治模式在每层递归时都有三个步骤:

1、分解:将原问题分解为若干子问题,这些子问题是原问题的规模较小的实例;

2、解决:递归的求解各子问题;

3、合并:合并子问题的解,得到原问题的解。

看到这里,“直觉”上可能会产生一个极大的疑问:最底层的子问题是在哪里解决的?产生这个疑问是正常的,因为第二步“解决”也仅仅是调用自身,其实就是重新进入了下一层的分解、解决和合并,而没有看到“如何解决”。

答案是:无需解决。换句话说,层层分解到子问题的规模足够小时,解就自己出现了。后面还会再提到这一点。

归并排序伪码

归并排序按照分治法的三个步骤如下:

  • 分解:分解待排序的n个元素的序列,变成各具n/2个元素的两个子序列;
  • 解决:递归的调用自身排序两个子序列;
  • 合并:合并两个已排序的子序列以产生最终排序的序列。

上一篇合并算法中已经解决了合并算法MERGE,归并排序就剩下如何进行分解,和递归调用了。

看代码的确就这三步:

MERGE-SORT(A, p, r) 1 if p < r 2 q = (p + r) / 2 3 MERGE-SORT(A, p, q) 4 MERGE-SORT(A, q+1, r) 5 MERGE(A, p, q, r)

注:(p + r) / 2如果不是整除,则取小于它的最大整数。

p < r时,表明数组有继续拆分的可能。当p ≥ r时,则表示该子数组最多有一个元素,所以无需排序就已经是排好序了,这就是分解到足够小会导致的自动解决。换句话说,我们一直把数组分解下去,直到分成每个子数组只包含1个元素时,即第3行中p = q,第4行中q+1 = r,那么第3和第4行的MERGE-SORT会立即返回,并执行MERGE,然后返回上一层MERGE-SORT,直到最上层。

一个例子

一个有8个元素的数组A[5, 2, 4, 7, 1, 3, 2, 6],采用归并排序的图示如下图。图中的下方蓝区部分是上面白区的数组不同时刻的镜像。

白区主要在做“分解”,蓝区主要在做“合并”。

归并排序

归并排序Java代码

public static void mergeSortInASC(int [] numbers, int p, int r) throws Exception {     if(p < r){        
 int q = (int)Math.floor((p + r) / 2);         
mergeSortInASC(numbers, p, q);         
mergeSortInASC(numbers, q + 1, r);         
mergeInASC(numbers, p, q, r);

   }
 }

MergeSort.java下载 (https://github.com/EthanYuan/algorithm/tree/master/src/algorithm)。

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-09-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习和数学

[编程经验] Python之collections模块

collections模块是一个不用不知道,一用就上瘾的模块。因为它提供了几种非常方便的数据结构和方法,在有些情况下特别好用。今天给大家总结一下其中的Order...

3194
来自专栏数据结构与算法

洛谷P3807 【模板】卢卡斯定理exgcd

题目背景 这是一道模板题。 题目描述 给定n 求  保证P为prime C表示组合数。 一个测试点内包含多组数据。 输入输出格式 输入格式: 第一行...

3046
来自专栏DHUtoBUAA

不使用额外空间交换2个数据的源代码

  最近做求职笔试题,遇到比较有意思的题目,题目或多或少涉及到《剑指Offer》的思路和知识点,如果不是刷书两遍,估计不会做出来,分享一下互相学习! *****...

2634
来自专栏python读书笔记

《算法图解》NOTE 5 散列表1.散列表简介2.散列表的特点2.1优点2.2缺点3.应用

1515
来自专栏java达人

哈希表

哈希表是种数据结构,它可以提供快速的插入操作和查找操作。第一次接触哈希表时,它的优点多得让人难以置信。不论哈希表中有多少数据,插入和删除(有时包括侧除)只需要接...

1637
来自专栏take time, save time

你所能用到的数据结构(五)

七、骚年,这就是你的终极速度了吗? 在介绍了前面的几个排序算法之后,这一次我准备写写快速排序,快速排序之所以叫快速排序是因为它很快,它是已知实践中最快的排序算...

2655
来自专栏云霄雨霁

排序算法总结

950
来自专栏小樱的经验随笔

51 Nod 1007 正整数分组【类01背包】

1007 正整数分组 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 将一堆正整数分为2组,要求2组的和相差最小。 例如:1...

2547
来自专栏信数据得永生

JavaScript 编程精解 中文第三版 一、值,类型和运算符

3508
来自专栏社区的朋友们

sizeof 知多少? (上)

稍熟悉 C/C++ 的朋友,对于 sizeof 肯定不陌生,通过它我们可以知晓某个类型或者实例的内存大小( 以字节计 ),网上关于这个话题的信息其实挺多的,但是...

1070

扫描关注云+社区