第一部分--基础知识--第2章:算法入门--2.3分治法及合并排序

说明:该系列博客整理自《算法导论(原书第二版)》,但更偏重于实用,所以晦涩偏理论的内容未整理,请见谅。另外本人能力有限,如有问题,恳请指正!

1、本节摘要

    算法设计的方法有很多。插入排序 使用的是 增量 (incremental)方法:在排好子数组 A [ 1 .. j - 1 ]后,将元素 A [ j ]插入,形成排好序的子数组 A [ 1 .. j ]。

    在本节中,要介绍另一种设计策略,叫做“分治法”。下面要用分治法来设计一个排序算法,使其性能比插入排序好的多。学过第4章就可以知道,分治类算法的优点之一是可以利用在第4章中介绍的技术,很容易的确定其运行时间。

2、分治法思想介绍

    有很多算法在结构上是 递归 的:为了解决一个给定的问题,算法要一次或多次地递归调用其自身来解决相关子问题。这些算法通常采用 分治策略 (divide-and-conquer):将原问题划分成 n 个规模较小而结构与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。

    归并排序、动态规划算法、贪心算法这些常用的算法都是在“分治法”思想的基础上分析出来的,他们是分治法思想的体现。

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

            分解(Divide):将原问题分解成一系列子问题;

            解决(Conquer):递归地解各个子问题。若子问题足够小,则直接求解;

            合并(Combine):将子问题的结果合并成原问题的解。

3、归并排序(合并排序)

    归并排序(merge sort)完全依照了 分治策略,直观的操作如下:

            分解:将 n 个元素分成各含 n / 2个元素的子序列;

            解决:对两个子序列递归地排序;若子问题足够小,则直接求解(对子序列排序时,其长度为1时递归结束,因为单个元素被视为是已排好序的);

            合并:合并两个已排序的子序列以得到排序结果。

    归并排序的关键步骤在于合并两个已排序的子序列。这里引入一个辅助过程 MERGE(A, p, q, r) ,其中 A 为数组, p , q 和 r 都是下标,有 p <= q < r 。该过程假设子数组 A [ p .. q ]和 A [ q + 1 .. r ]都已排好序,并将它们合并成一个已排好序的子数组代替当前子数组 A [ p .. r ]。

    MERGE过程的时间代价为Θ(n),其中n = r - p + 1是待合并的元素个数。下面通过扑克牌的例子说明算法的工作过程:假设两堆牌都面朝上的放在桌上,每一堆都是已排序的,且最小的牌在最上面。我们希望把两堆牌合并成一个排好序的输出堆,且面朝下的放在桌上。合并过程为,在面朝上的两堆牌中,选取顶上两张中较小的一张,将其取出后面朝下的放到输出堆中。重复这个步骤,直到某一输入堆为空时为止。这时把输入堆中余下的牌 面朝下的放入输入堆中即可。从计算的角度来看,每一个基本步骤所花时间是个常亮,因为我们只是查看并比较顶上的两张牌,又因至多进行n次比较,所以MERGE过程的时间复杂度为Θ(n)。

    下面的伪代码实现了上述思想,但有一个小的优化,即在两个子堆中增加了∞这个哨兵,来避免检查两个子堆是否为空。一旦出现两个哨兵牌同时出现时,说明两堆牌中非哨兵的牌都已经被放到输出堆中去了,因为预先直到只有r - p + 1张牌会被放到输出堆中去,因此此时也是执行了r - p + 1个基本步骤了,循环可以停止了。

MERGE(A, p, q, r)

1      n1 = q - p + 1

2      n2 = r - q

3      //let L[1 .. n1 + 1] and R[1 .. n2 + 1] be new arrays

4      for i = 1 to n1

5          L[i] = A[p + i - 1]

6      for j = 1 to n2

7          R[j] = A[q + j]

8      L[n1 + 1] = MAX

9      R[n2 + 1] = MAX

10     i = 1

11     j = 1

12     for k = p to r

13         if L[i] <= R[j]

14             A[k] = L[i]

15             i = i + 1

16         else

17             A[k] = R[j]

18             j = j + 1

    下面说明完整的归并排序过程MERGE-SORT,其中 MERGE 过程作为归并排序中的一个子程序来使用。MERGE-SORT(A, p, r) 对子数组 A [ p .. r ]排序。如果 p >= r ,则该子数组中至多只有一个元素,视为已排序。否则,分解步骤就计算出一个下标 q ,将 A [ p .. r ]分成 A [ p .. q ]和 A [ q + 1 .. r ],各含 FLOOR(n / 2) 1 个元素。

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)

    下图自底向上地展示了当 n 为2的幂时,整个过程中的操作。算法将两个长度为1的序列合并成已排好序的、长度为2的序列,接着又将长度为2的序列合并成长度为4的序列,直到最终形成排好序的 n 的序列。

4、归并排序时间复杂度分析

    这里只说明分析结果,分析过程请参考《算法导论(原书第二版)》。归并排序 的总代价为cn(lgn + 1) = cn * lgn + cn,忽略低阶项和常亮c,即得到结果Θ(n * lgn)。

    需要说明的是,忽略低阶项和常亮c的前提是输入规模n很大。使用归并排序时一般输入规模都很大,输入规模很小时一般采用的是插入排序

5、练习

二分查找伪码:

BINARY-SEARCH(A, v)

1  front = 1

2  end = A.length

3  while front < end

4      middle = (front + end) / 2

5      if A[middle] < v

6          front = middle + 1

7      else if A[middle] > v

8          end = middle - 1

9      else

10        return middle

11 return -1

6、参考文档

    算法导论读书笔记(2)

    合并排序,该文章中的两点改进很好:1)、分割为合适长度的小序列后使用插入排序,然后将经过插入排序的小序列进行合并排序;2)、算法中对两个小序列进行合并操作之前,先对其中值点进行比对,如果符合期望的升/降序目标,则不用再经过合并操作,直接连接起来即可。

    C语言合并排序及实例代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,164评论 0 52
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,727评论 0 15
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 1,239评论 0 2
  • 前阵子,我堂哥生了个大胖小子,大伯家满堂喜。一周前,我姐姐生了个女儿,大家一阵惋惜,“要是男孩就好了……” 我妈有...
    落叶之上阅读 4,005评论 3 2
  • 作者:小宋老师 不管你是否承认,在每个人的思维当中,都存在着一些错误的思维方式。这些错误的思维方式,就像是一堵堵无...
    Gordon_zhu阅读 319评论 0 0