【算法基础】由插入排序来看如何分析和设计算法

来源:互联网 发布:剑网三mac可以玩吗 编辑:程序博客网 时间:2024/06/05 04:35

插入排序及其解决思路

算法的作用自然不用多说,无论是在校学生,还是已经工作多年,只要想在计算机这条道路走得更远,算法都是必不可少的。

就像编程语言中的“Hello World!”程序一般,学习算法一开始学的便是排序算法。排序问题在日常生活中也是很常见的,说得专业点:

输入是:n个数的一个序列<a1,a2,...,an1,an> 
输出是:这n个数的一个全新的序列<a,1,a,2,...,a,n1,a,n>,其特征是a,1a,2...a,n1a,n

举个例子,在本科阶段学校往往要求做的实验中大多是“学生管理系统”、“信息管理系统”、“图书管理系统”这些。就比如“学生管理系统”中的分数,每当往里面添加一个新的分数时,便会和其他的进行比较从而得到由高到低或由低到高的排序。

我本人是不太喜欢做这种管理系统的…… 再举个比较有意思的例子。

大家肯定都玩过扑克牌,撇开部分人不说,相信大部分童鞋都热衷于将牌按序号排好。那么这其中就蕴含着算法的思想:

<code class="hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">1)手中的扑克牌有2种可能:没有扑克牌(为空)或者有扑克牌且已排好序。2)从桌上抓起一张牌后,从左往右(从右往左)依次进行比较,最终选择一个合适的位置插入。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

简单的说,插入排序的精髓在于“逐个比较”。

在列出代码之前,先来看看下面的第一张图,我画的不是太好,就是有没有经过排序的 “8,7,4,2,3,9”几个数字,根据上面的描述,将排序过程描述为:

<code class="hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">1)将第二个数字“7”和“8”比较,发现7更小,于是将“8”赋值到“7”所在的位置,然后将7赋值给“8”所在的位置。2)将”4“移到”7“所在的位置,”7“和”8“后移一位。3)同样的步骤,将”2“和”3“移到”4“的前面。4)”9“比前面的数字都大,故不移动。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

这里写图片描述

仅仅是这样的描述还是不够的,我们需要更加专业一点。

<code class="hljs matlab has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)设置一个循环,从第二个数字开始(索引为<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)不断与前面的数字相比。<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)每次循环开始时作为比较的数的索引为<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">j</span>,设置temp为其值。(因为在前面也看到了,将”<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>“赋值到”<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>“的位置时,如果不将”<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>“保存起来,那么便丢失了这个数字。)<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)取得<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">j</span>的前一位<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>。<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>)只要<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>仍在数组中,并且索引为<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>处的值大于temp,就将<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>后一位的值设为<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>处的值,同时将<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>减<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>。<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>)在<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>不在数组中或<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>处的值不必temp大时结束第四部的循环,然后将<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>后一位的值设置为temp。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

将上面这部分描述翻译为insertion_sort函数,下面是完整的测试程序。

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <cstdio></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#define MAX_N 1000</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[MAX_N];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> insertion_sort();<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(){    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"数组长度:\n"</span>);    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">scanf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d"</span>,&n);    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"数组内容:\n"</span>);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<n;i++)    {        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">scanf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d"</span>,&A[i]);    }    insertion_sort();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<n;i++)    {        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d "</span>,A[i]);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> insertion_sort(){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;j<n;j++)    {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> temp=A[j];        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=j-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(i>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>&&A[i]>temp)        {            A[i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]=A[i];            i=i-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;        }        A[i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]=temp;    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li></ul>

下面是能够帮助我们理解算法的正确性的循环不变式的三条性质:

<code class="hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">初始化:循环第一次迭代之前,它为真。保持:如果循环的某次迭代之前它为真,那么下次迭代之前它仍为真。终止:在循环终止时,不变式能够提供一个有助于证明算法正确性的性质。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

就比如上面排序的例子,终止意味着在最后一次迭代时,由传入数组元素构成的子数组元素都已排好序,因此此时子数组就等同与原数组,于是循环终止。

学习如何分析算法

继续分析排序算法,我们知道排序10000个数肯定要比排序10个数所花费的时间更长,但除了输入的项数外就没有其他的影响因素吗?当然有,比如说输入的序列的已被排序的程度,如果是“23456781”这个序列,我们仅仅需要将1放到首位就好,而输入是”87654321“,我们就需要将7到1依次与其前面的数字进行比较。

关于算法的分析也有两个定义:

<code class="hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">1)输入规模,当考虑的是排序算法时,那么规模就指的是项数;如果考虑的是图算法,那么规模就是顶点数和边数。2)运行时间,名义上来说就是算法执行的时间,但实际上我们在分析一个算法时考量的算法执行的操作数或步数。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

下面我们通过前面排序算法的伪代码来分析它的运行时间。

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">INSERTION-SORT(A)<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> A.<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">length</span>                 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 代价c1,次数n   </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>       temp=A[j];                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 代价c2,次数n-1</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 将A[j]插入到已排序的A[1..j-1]      // 代价0,次数n-1</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>       i=j-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;                            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 代价c4,次数n-1</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>       <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> i><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> <span class="hljs-operator" style="box-sizing: border-box;">and</span> A[i]>temp           <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 代价c5  </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>           A[i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]=A[i];                  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 代价c6</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>           i=i-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 代价c7       </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>       A[i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]=temp;                      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> // 代价c8,次数n-1</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

代价为c1处的次数为n应该比较好理解对吧,从j=1到j=n一共有n步,j=n也应该包括在内,因为这是算法终止的情况。而j=n时,程序直接终止了,所以在代价c2、c3、c7处次数都为n-1。

那么在while循环中呢,代价为c4的时候次数为多少呢,很显然应该是nj=2tj,而c5和c6在while循环里总有一次它不会去执行,因此次数为nj=2(tj1)

将代价和次数相乘,便得到了该算法所需的总时间: 
T(n)=c1n+c2(n1)+c4(n1)+c5nj=2tj+c6nj=2(tj1)+c7nj=2(tj1)+c8(n1)

除此之外我们还可以来对算法进行最好和最坏情况的分析: 
1)在最好情况下,也就是整个输入数组其实都是排好序的,那么它根本没法进入while循环,也就是说当i取初值j-1时,有A[i]temp,从而对j=2,3,4...n都有tj=1

那么算法的总时间也就可以算出来了: 
T(n)=(c1+c2+c4+c5+c8)n(c2+c4+c5+c8)

2)在最坏情况下,也就是数组是逆向排好序的,那么就需要将A[j]与已排好序的数组A[1...j1]中的每个元素进行比较,从而对j=2,3,4...n都有tj=j

那么算法的总时间也就可以算出来了: 
T(n)=(c52+c62+c72)n2+(c1+c2+c4+c52c62c72+c8)n(c2+c4+c5+c8)

渐近记号

Θ 
在上面我已经求出了该排序算法的运行总时间,但我们可以对其做进一步的简化以及抽象,我们只考虑最坏情况,因为在实际中它更有意义。将运行时间表示为an2+bn+c,其中的abc都依赖于ci

让我们来做进一步的抽象,通过只考虑运行时间的增长率和增长量级。因为当程序足够大时,低阶项便不再重要了,甚至连高阶项的系数也可以忽略不计。于是,我们记插入排序在最坏情况下所需要的运行时间为Θ(n2)

现在是时候给出Θ的定义了: 
Θ(g(n))={f(n):c1c2n0使nn0,0c1g(n)f(n)c2g(n)}

也就是说在跨过n0之后,f(n)就一直处于c1g(n)c2g(n)之间,其中c1g(n)是下界,c2g(n)是上界。

OΩ

OΘ相比,前者就只是后者的一半——只有渐近上界,而没有渐近下界。那么它的定义为: 
O(g(n))={f(n):cn0使nn0,0f(n)cg(n)}

ΩΘ相比,前者就只是后者的一半——只有渐近下界,而没有渐近下界。那么它的定义为: 
Ω(g(n))={f(n):cn0使nn0,0f(n)cg(n)cg(n)}

设计分治算法

前面的排序问题使用的方法叫做增量法,即在排序子数组A[1...j1]后,将单个元素A[j]插入到子数组的适当位置,然后参数排序好的数组A[1...j],它的精髓在于“逐个比较”。

现在我们再来介绍一种新的方法,叫做分治法,它同样也是鼎鼎大名。它的精髓在于“一分为二“,而驱动这个算法的这是递归。

分治算法在每层递归中都有三个步骤:

<code class="hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">1)分解原问题为若干子问题,这些子问题是缩小版的原问题。(抽象的讲,将一个已经切成楔形的大块西瓜可以再切成多个小的楔形西瓜。)2)解决这些子问题,递归地求解各个子问题。然后,若问题的规模足够小,则直接求解。(继续举例子,要吃完一大块西瓜,可以不断的吃小部分,当西瓜块足够小时,可以一口干掉。)3)合并这些子问题的解成原问题的解。(吃完的那些小块西瓜加在一起就是刚才那一块很大的西瓜了。)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

虽然西瓜的例子能够体现分治算法的思想,但用前面的扑克牌来演示则更加合适,毕竟它有数字呀。来来来,想象一下,桌上正有两堆牌,且分别都已经排号顺序,可是呢我们需要这两堆牌合并起来并且排序好。

那么怎么操作呢?很简单,一句话就能说清楚:不断从两堆牌的顶上选取较小的一张,然后放到新的扑克牌堆中。

首先我们将扑克牌定义成数组Apq以及r都是数组的下标,且pq<r,两段已排序好的子数组是A[p..q]A[q+1..r],我们需要做的是将其排序为A[p..r]。下面的伪代码便实现了这个思想:

<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">MERGE(A,p,q,r)<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>  n1 = (q - p) + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> = q - p + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>  n2 = (r - (q + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)) +<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> = r - q<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> L[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span>.n1+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> R[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.</span>.n2+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] be <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> arrays<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> n1<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>      L[i] = A[p + i -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> n2<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>      R[j] = A[q + j]<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>  L[n1 + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span>  R[n2 + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">11</span> j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> k = p <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> r<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span>     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> L[i] 小于等于 R[j]<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>        A[k] = L[i];<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">15</span>        i = i + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span>        A[k] = R[j]<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>        j = j + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

上面的”# “号就是传说中的哨兵牌,每当显露一张哨兵牌时,它不可能为较小的值,除非两个堆都已显露出哨兵牌。但是出现这种情况就意味着算法结束,所有非哨兵牌都已被放置到输出堆。

<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">………………p     q       r………………………………<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>………………        kL <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#     R 2 5 7 8 #</span>  i               j</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

比较”3“和”2“,发现2更小,于是将2放到A数组的首位,并且将j移后一位。

<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">………………p     q       r………………………………<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>………………          kL <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#     R 2 5 7 8 #</span>  i                 j</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

比较”3“和”5“,发现3更小,于是将3放到数组A的首位,并且将i移后一位。

<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">………………p     q       r………………………………<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>………………            kL <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#      R 2 5 7 8 #</span>    i                j</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

以此类推,最终A数组就成排好了序……

<code class="hljs ruleslanguage has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">………………p     q       r………………………………<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span>………………                      kL <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> <span class="hljs-array" style="box-sizing: border-box;">#      R </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> <span class="hljs-array" style="box-sizing: border-box;">#    </span>          i                j</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

将上面的思想以及伪代码写成如下程序,大家可以参考参考:

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <cstdio></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#define MAX_N 1000</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[MAX_N];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> L[MAX_N/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> R[MAX_N/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n,p,q,r;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> merge();<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(){    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"数组长度:\n"</span>);    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">scanf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d"</span>,&n);    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"数组内容:\n"</span>);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<n;i++)    {        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">scanf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d"</span>,&A[i]);    }    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"输入p q r\n"</span>);\    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">scanf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d %d %d"</span>,&p,&q,&r);    merge();    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<n;i++)    {        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d "</span>,A[i]);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> merge(){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n1=q-p+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n2=r-q;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<n1;i++)        L[i]=A[p+i];    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;j<n2;j++)        R[j]=A[q+j+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];    L[n1]=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;    R[n2]=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> k=p,i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,j=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;k<=r;k++)    {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(L[i]<=R[j])        {            A[k]=L[i];            i=i+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>        {            A[k]=R[j];            j=j+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;        }    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li></ul>

下面没有用图示而是用了代码显示块来显示,应该也能看的吧?就是不断的归并,最终合成一个完整的排好序的数组。

<code class="hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">…………………………2 2 5 6 7 8 8 9………………………………………………………………归并………………………………………………………2 5 6 8………………2 7 8 9………………………………………归并…………………………归并…………………………………2 6…………5 8…………2 9…………7 8…………………………归并…………归并………归并……………归并………………………6……2………8……5………2……9………8……7…………</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

要完成上面这个程序,我们可以利用前面写好的merge函数呢,下面是伪代码实现。

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">MERGE</span>-SORT(A,p,r)<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> p < r<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>      q = 小于或等于(p+r)/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>的最大整数<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">MERGE</span>-SORT(A,p,q)<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">MERGE</span>-SORT(A,q+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,r)<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">MERGE</span>(A,p,q,r)</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

然后为了完成这其中q的参数传递,将它们设置为全局变量已经不合适了,具体的程序可以参考如下:

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <cstdio></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#define MAX_N 1000</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[MAX_N];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> L[MAX_N/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> R[MAX_N/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> merge(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[],<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> q,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> r);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> merge_sort(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[],<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> r);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n, p, q, r;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"数组长度:\n"</span>);    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cin</span> >> n;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"数组内容:\n"</span>);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i < n;i++)    {        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cin</span> >> A[i];    }    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"输入p r\n"</span>);\        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cin</span> >> p >> r;    merge_sort(A, p, r);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i < n;i++)    {        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d "</span>, A[i]);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> merge_sort(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[],<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> r){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(p<r)    {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> q=(p+r)/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        merge_sort(A,p,q);          merge_sort(A,q+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,r);        merge(A,p,q,r);    }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> merge(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[], <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> q, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> r){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n1 = q - p + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n2 = r - q;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<n1;i++)        L[i] = A[p + i];    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;j<n2;j++)        R[j] = A[q + j + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];    L[n1] = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;    R[n2] = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> k = p, i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;k<=r;k++)    {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (L[i] <= R[j])        {            A[k] = L[i];            i = i + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>        {            A[k] = R[j];            j = j + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;        }    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li></ul>

一起来分析分治算法

当我们的输入足够小时,比如对于某个常量c,nc,则直接求解需要常量时间,并写作Θ(1)

对于复杂的问题,我们将其分解成a个子问题,每个子问题的规模是原问题的1/b.对于这规模为n/b的子问题,累计需要T(n/b)的时间,所以需要aT(n/b)的时间来求解这a个子问题。而这其中分解的过程也需要消耗一定的时间,记作D(n),合并这些子问题也需要一定的时间,记作C(n)。于是又得到了一个递归式:

nc时,T(n)=Θ(1)

其他情况时,T(n)=aT(n/b)+D(n)+C(n)

下面来通过分治模式在每层递归时都有的三个步骤来分析归并排序算法,我们所考虑的是n个数的最坏情况下的运行时间。同样的,归并排序一个元素需要常量时间,当n>1时有如下3个步骤:

分解:分解步骤仅仅计算子数组的中间位置,需要常量时间,因此D(n)=Θ(1) 
解决:我们递归地求解两个规模均为n/2的子问题,将贡献2T(n/2)的运行时间。 
合并:一个具有n个元素的子数组上过程MERGE需要Θ(n)的时间,所以C(n)=Θ(n)

因此D(n)+C(n)便等于Θ(n)Θ(n)相加,可是结果依然为Θ(n)。接着可以得到归并排序的最坏情况运行时间的递归式了。

n=1时,T(n)=Θ(1)

n>1时,T(n)=2T(n/2)+Θ(n)

我们对上式稍作变换如下:

n=1时,T(n)=c

n>1时,T(n)=2T(n/2)+cn

这个式子可以不断的做递归,最后形成一个递归树的。树的第一层是cn,第二层是cn/2,第三层是cn/4,直到最后一层为c。第二层有2棵子树,第三层有4棵子树,直到最后一程有n棵子树,因此每层的代价总共为cn。而整个树共有lgn+1层,因此总代价为cnlgn+cn

忽略低阶项和系数项,最终记为Θ(nlgn)

递归和迭代

这两个概念也许很多童鞋依旧是老虎老鼠傻傻分不清楚,下面通过求解斐波那契数来看看它们俩的关系吧。

斐波那契数的定义: 

f0=0

f1=1

fi=fi1+fi2(i>1)

递归:

<code class="hljs lisp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>)</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)</span>)</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)</span>)</span>)</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)</span>)</span>)</span>)</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)</span>)</span>)</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> (<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">* 3 2))))(*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">24</span>)</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">*</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">120</span>)</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">720</span></span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

迭代:

<code class="hljs lisp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">24</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">120</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">factorial</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">720</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>)</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">720</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

递归的核心在于:不断地回到起点。 
迭代的核心在于:不断地更新参数

在下面的代码中:

递归的核心是sum的运算,sum不断的累乘,虽然运算的数值不同,但形式和意义一样。

而迭代的核心是product和counter的不断更新。如上表中,product就是factorial的前2个参数不断的累乘更新成第一个参数;而第二个参数则是counter,其不断的加1来更新自己。

<code class="hljs haskell has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-title" style="box-sizing: border-box;">product</span> <- counter * product <span class="hljs-title" style="box-sizing: border-box;">counter</span> < - counter + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> factorialRecursive(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> factorialIteration(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> product, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> counter, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> max_count);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Enter an integer:"</span><<endl;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cin</span>>>n;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<factorialRecursive(n)<<endl;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<factorialIteration(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,n)<<endl;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> factorialRecursive(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> sum=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(n==<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)        sum*=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>        sum=n*factorialRecursive(n-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> sum;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> factorialIteration(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> product, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> counter, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> max_count){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> sum=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(counter>max_count)        sum*=product;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>        factorialIteration((counter*product),(counter+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>),max_count);}</code>
0 0