分治(Divide and Conquer)算法之归并排序
Posted spacerunnerZ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治(Divide and Conquer)算法之归并排序相关的知识,希望对你有一定的参考价值。
顾名思义,分治问题由“分”(divide)和“治”(conquer)两部分组成,通过把原问题分为子
问题,再将子问题进行处理合并,从而实现对原问题的求解。我们在排序章节展示的归并排序就
是典型的分治问题,其中“分”即为把大数组平均分成两个小数组,通过递归实现,最终我们会
得到多个长度为1 的子数组;“治”即为把已经排好序的两个小数组合成为一个排好序的大数组,
从长度为1 的子数组开始,最终合成一个大数组。
分治策略Divide and Conquer
在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,通常是递归算法,就是 把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换。
任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可…而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。
分治策略的基本思想
分治算法是 将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。如果原问题可分割成
k
个子问题,
熟悉的例子
二分查找: 给定已按升序排好序的
n
个元素
算法 1 binarysearch(T,x)
输入:排好序的数组 T ;数x
输出: j
1.l⟵1;r⟵n
2. while l≤r do
3. m⟵⌊l+r2⌋
4. if T[m]=x then return m
5. else if T[m]≥x then r⟵m−1
6. else l⟵m+1
7. return 0
分析:
1、该问题的规模缩小到一定的程度就可以容易地解决;
2、该问题可以分解为若干个规模较小的相同问题;
3、分解出的子问题的解可以合并为原问题的解;
4、分解出的各个子问题是相互独立的。
很显然此问题分解出的子问题相互独立,即在 a[i] 的前面或后面查找x是独立的子问题,因此满足分治法的第四个适用条件。
#include <iostream>
using namespace std;
// 查找成功返回value索引,查找失败返回-1
template <class T>
int binary_search(T array[],const T& value,int left,int right)
while (right >= left)
int m = (left + right) / 2;
if (value == array[m])
return m;
if (value < array[m])
right = m - 1;
else
left = m + 1;
return -1;
int main()
int array[] = 0,1,2,3,4,5,6,7,8,9;
cout << "0 in array position: " << binary_search(array,0,0,9) << endl;
cout << "9 in array position: " << binary_search(array,9,0,9) << endl;
cout << "2 in array position: " << binary_search(array,2,0,9) << endl;
cout << "6 in array position: " << binary_search(array,6,0,9) << endl;
cout << "10 in array position: " << binary_search(array,10,0,9) << endl;
return 0;
算法复杂度分析:
每执行一次算法的while循环, 待搜索数组的大小减少一半。因此,在最坏情况下,while循环被执行了O(logn) 次。循环体内运算需要O(1) 时间,因此整个算法在最坏情况下的计算时间复杂性为O(logn) 。
上述算法就是用分治算法,它们的共同特点是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
分治算法的一般性描述
对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。分治算法divide-and-conquer的伪码描述如下:
算法2: divide−and−conquer(P)
1. if(|P|≤c) S(P) // 解决小规模的问题
2. divide P into smaller subinstances P1,P2,…,Pk //分解问题
3. for i=1 to k do
4. yi←divide−and−conquer(Pi) //递归的解各子问题
5. ReturnMerge(y1,y2,以上是关于分治(Divide and Conquer)算法之归并排序的主要内容,如果未能解决你的问题,请参考以下文章