算法设计与分析 第2章
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
分治法的基本步骤
divide-and-conquer(P)
{ if ( | P | <= n0) adhoc(P); //解决小规模的问题 divide P into smaller subinstances P1,P2,...,Pk;//分解问题
for (i=1,i<=k,i++) yi=divide-and-conquer(Pi); //递归的解各子问题 return merge(y1,...,yk); //将各子问题的解合并为原问题的解
T(n)
=n
n/2
n/2
n/2
n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
算法总体思想
将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
分分治割T法成(n的一) 设些计规思模想较是小=,的将相一同n个问难题以,直以接便解各决个的击大破问,题,
分而治之。
n/2
n/2
n/2
n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
T(n)
=n
n/2
n/2
n/2
n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
算法总体思想
将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
2.1 递归的概念
例3 Hanoi塔问题 在当vo问nid=题1h时a规n,模oi问较(in题大t n比时, i较,nt 简较a,单难in。找t b此到, in时一t ,般c) 只的要方将法编,号因为此1我的们圆尝盘试从塔座a 用直递接{ 归移技至术塔来座解b上决即这可个。问题。 当较大n小圆>的盘i{f1圆从(时n盘塔,> 依座0需)照a要移移利至动用塔规塔座则座b从,c作塔最为座后辅a,移助再至塔设塔座法座。将c此,n时-然1若个后能较,设小将法的剩将圆下n盘的-1依最个 照移动规ha则no从i(塔n-1座, ac移, c至, b塔); 座b。 由此可见mo,vne个(a,圆b)盘; 的移动问题可分为2次n-1个圆盘的移动问题, 这又可以ha递no归i(地n-1用, c上, 述b, 方a)法; 来做。由此可以设计出解Hanoi塔问 题的递} 归算法如下。
wenku.baidu.com
算法总体思想
对这k个子问题分别求解。如果子问题的规模仍然不够 将小要,求则解再的划较分大为k规个模子的问问题题,分如割此成递k归个的更进小行规下模去的,子直问
题到。问题规模足够小,很容易求出其解为止。
T(n)
=n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
算法总体思想
对将这求k出个的子小问规题模分的别问求题解的。解如合果并子为问一题个的更规大模规仍模然的不问够 小题,的则解再,划自分底为向k上个逐子步问求题出,原如来此问递题归的的解进。行下去,直 到问题规模足够小,很容易求出其解为止。
细可2节能. 问得X题到Y:m=+两1个a位cX的Y2的结n复果+杂,度(使(都a问+是题cO的)((规nblo模g+3)变d,)大但-a,考c故虑-不b到d选a)+择c2第,bn+2/2种d+ 方案。bd
{
if (n <= 1) return 1;
return fibonacci(n-1)+fibonacci(n-2);
}
2.1 递归的概念
例3 Hanoi塔问题 设a,b,c是3个塔座。开始时,在塔座a上有一叠共n个圆盘,这 些圆盘自下而上,由大到小地叠在一起。各圆盘从小到大编号 为1,2,…,n,现要求将塔座a上的这一叠圆盘移到塔座b上,并仍 按同样顺序叠置。在移动圆盘时应遵守以下移动规则: 规则1:每次只能移动1个圆盘; 规则2:任何时刻都不允许将较大的圆盘压在较小的圆盘之上; 规则3:在满足移动规则1和2的前提下,可将圆盘移至a,b,c中 任一塔座上。
每执行一次算法的while循环, 待
int m = (l+r)/2;
搜索数组的大小减少一半。因此,
if (x == a[m]) return m;
在最坏情况下,while循环被执行了
if (x < a[m]) r = m-1; else l = m+1; O(logn) 次。循环体内运算需要O(1)
{ if (left<right) {//至少有2个元素 int i=(left+right)/2; //取中点 mergeSort(a, left, i); mergeSort(a, i+1, right); merge(a, temp, left, I, right); //合并到数组temp copy(a, temp, left, right); //复制回数组a }
}
递归小结
优点:结构清晰,可读性强,而且容易用 数学归纳法来证明算法的正确性,因此它 为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是 耗费的计算时间还是占用的存储空间都比 非递归算法要多。
分治法的适用条件
分治法所能解决的问题一般具有以下几个特征:
该问题的规模缩小到一定的程度就可以容易地解决; 该问题可以分解为若干个规模较小的相同问题,即该
2.1 递归的概念
例2 Fibonacci数列 无穷数列1,1,2,3,5,8,13,21,34,55,……,称为 Fibonacci数列。它可以递归地定义为:
1
n0
F (n)
1
n 1
F (n 1) F (n 2) n 1
边界条件 递归方程
第n个Fibonacci数可递归地计算如下:
int fibonacci(int n)
问题具有最优子结构性质 利用该问题分解出的子问题的解可以合并为该问题的
解; 该问题所分解出的各个子问题是相互独立的,即子问
题之间不包含公共的子问题。
因这能为条否问特利题征用的是分涉计应治及算用法到复分完杂治全性法取一的决般前于效是提问率随,题着它是如问也否果题是具各规大有子模多这问的数条题增问特是加题征不, 而可如独增以果立加满具的,足备因的了则此,前分大此两治部特条法分征特要问反征做题映,许满了而多足递不这归具必个思备要特想第的征的三工。应条作用特,征重,复则地 可解以公考共虑的子贪问心题算,法此或时动虽态然规也划可。用分治法,但一般 用动态规划较好。
数 temp中。
组
合
并
合并排序
算法mergeSort的递归过程可以消去。 初始序列 [49] [38] [65] [97] [76] [13] [27]
第一步 第二步
[38 49] [65 97] [13 76] [27]
[38 49 65 97]
[13 27 76]
第三步
[13 27 38 49 65 76 97]
T(n)=O(n2) 没有改进
大整数的乘法
请设计一个有效的算法,可以进行两个n位大整数的乘法运算
小学的方法:O(n2)
效率太低
分治法:
XY = ac 2n + (ad+bc) 2n/2 + bd
为了降低时间复杂度,必须减少乘法的次数。
1. XY = ac 2n + ((a-c)(b-d)+ac+bd) 2n/2 + bd
第2章 递归与分治策略
学习要点: • 理解递归的概念。 • 掌握设计有效算法的分治策略。 • 通过下面的范例学习分治策略设计技巧。 • (1)二分搜索技术; • (2)大整数乘法; • (3)Strassen矩阵乘法; • (4)合并排序和快速排序; • (5)线性时间选择; • (6)最接近点对问题; • (7)循环赛日程表。
分治与递归像一对孪生兄弟,经常同时应用在 算法设计之中,并由此产生许多高效算法。
2.1 递归的概念
例1 阶乘函数 阶乘函数可递归地定义为:
1 n0 n! n(n 1)! n 0
边界条件 递归方程
边界条件与递归方程是递归函数的二个要素,递归函 数只有具备了这两个要素,才能在有限次计算后得出 结果。
} return -1; }
时间,因此整个算法在最坏情况下 的计算时间复杂性为O(logn) 。
合并排序
基本思想:将待排序元素分成大小大致相同的2个子集合,分 别对2个子集合进行排序,最终将排好序的子集合合并成为所 要求的排好序的集合。
void MergeSort(Type a[], int left, int right)
✓ 该问题可以分解为若干个规模较小的相同问题;
✓ 分解出的子问题的解可以合并为原问题的解;
分析✓:分比解较出x和的a各的个中子间问元题素是a[相mi互d]独,立若的x=。a[mid],则x在L中的 分可用位如a的分面用[m析以条置x后析或条在id:确件就面:后件]a的定是查面。如很中前找查果xm显的是面i找然nx话d否即=;查此x,1在可是如即找问x表。独必果只x题即中无立然x有分<可。论的排a一解;[因是子m在个出如i此在问ad元的[]果m,这前题素子ix由d个面,,>]问的a于问还因则[题i前]a题是此,只是相面满后满同要递互,足面足理比增独所分查分我较排立以治找治们这序,我法法x只个的,即们的的要元,其在只第第在素因方a要一四[a和i此法][在的m个个x假都就i前适适d] 和在a中查找x一样,只不过是查找的规模缩小了。这就说明 了此问题满足分治法的第二个和第三个适用条件。
} 人们从大量实践中发现,在用分治法设计算法时, 最好使子问题的规模大致相同。即将一个问题分成 大小相等的k个子问题的处理方法是行之有效的。 这种使子问题规模大致相等的做法是出自一种平衡 (balancing)子问题的思想,它几乎总是比子问题 规模不等的做法要好。
分治法的复杂性分析
一个分治法将规模为n的问题分成k个规模为n/m的子问题去 解。设分解阈值n0=1,且解规模为1的问题耗费1个单位时间。 再设将原问题分解为k个子问题以及用merge将k个子问题的解 合并为原问题的解需用f(n)个单位时间。用T(n)表示该分治法解 规模为|P|=n的问题所需的计算时间,则有:
2.1 递归的概念
直接或间接地调用自身的算法称为递归算法。 用函数自身给出定义的函数称为递归函数。
由分治法产生的子问题往往是原问题的较小模 式,这就为使用递归技术提供了方便。在这种 情况下,反复应用分治手段,可以使子问题与 原问题类型一致而其规模却不断缩小,最终使 子问题缩小到很容易直接求出其解。这自然导 致递归过程的产生。
}
复杂度分析
T
(n)
2T (n
O(1) / 2)
O(n)
n1 n 1
T(n)=O(nlogn) 渐进意义下的最优算法 辅助空间:O(n)
例
有
两个指针分别指向两个待合并数组的第一个元素,将较小元素添 加到temp数组。被复制数组的指针后移。重复上述操作,直到其
序 中一个数组被处理完成。将未处理完的数组中剩余的元素复制到
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。
据此容易设计出二分搜索算法:
template<class Type>
int BinarySearch(Type a[], const Type& x, i算nt l,法int复r) 杂度分析:
{ while (r >= l){
O(1)
n 1
T (n) kT(n / m) f (n) n 1
通过迭代法求得方程的解:T (n)
nlogm k
logm n1
kj
f (n / m j )
j0
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。 分析:✓ 该问题的规模缩小到一定的程度就可以容易地解决;
大整数的乘法
请设计一个有效的算法,可以进行两个n位大整数的乘法运算
小学的方法:O(n2)
效率太低
分治法:
X=
a
b
Y=
c
d
X = a 2n/2 + b Y = c 2n/2 + d XY = ac 2n + (ad+bc) 2n/2 + bd
复杂度分析
O(1)
n 1
T (n) 4T (n / 2) O(n) n 1