第二章递归与分治策略
合集下载
第2章 递归与分治(1)

分析:前面的几个例子中,问题本身都具有比较 明显的递归关系,易用递归函数直接求解。
本例若设p(n)为正整数n的划分数,则难以找到递 归关系。
17
现考虑增加一个自变量:将最大加数n1不大于m的划 分个数记作q(n,m)。q(n,m)有如下递归关系:
(1) q(n,1)=1,n1; 当最大加数n1不大于1时,任何正整数n只有一种划分形式, 即
• (8)循环赛日程表。
2
算法总体思想
对这k个子问题分别求解。如果子问题的规模仍然不够 将小要,求则解再的划较分大为k规个模子的问问题题,分如割此成递k归个的更进小行规下模去的,子直问
题到。问题规模足够小,很容易求出其解为止。
T(n)
=n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
3
算法总体思想
以想象的慢速度趋向正无穷大。
13
例4:排列问题
排设列计。一个递归算法生成n个元素{r1,r2,…,rn}的全 ➢设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R{ri}。 ➢集合X中元素的全排列记为perm(X)。 (permutation) ➢(ri)perm(X)表示在全排列perm(X)的每一个排列前 加上前缀得到的排列。
22
➢由此可见,n个圆盘的移动问题可分为2次n-1个圆 盘的移动问题,这又可以递归地用上述方法来做。
解Hanoi塔问题的递归算法如下:
void hanoi(int n, int a, int b, int c) { if (n > 0) { hanoi(n-1, a, c, b); move(a,b); hanoi(n-1, c, b, a); } }
n1,m1 nm nm
本例若设p(n)为正整数n的划分数,则难以找到递 归关系。
17
现考虑增加一个自变量:将最大加数n1不大于m的划 分个数记作q(n,m)。q(n,m)有如下递归关系:
(1) q(n,1)=1,n1; 当最大加数n1不大于1时,任何正整数n只有一种划分形式, 即
• (8)循环赛日程表。
2
算法总体思想
对这k个子问题分别求解。如果子问题的规模仍然不够 将小要,求则解再的划较分大为k规个模子的问问题题,分如割此成递k归个的更进小行规下模去的,子直问
题到。问题规模足够小,很容易求出其解为止。
T(n)
=n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
3
算法总体思想
以想象的慢速度趋向正无穷大。
13
例4:排列问题
排设列计。一个递归算法生成n个元素{r1,r2,…,rn}的全 ➢设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R{ri}。 ➢集合X中元素的全排列记为perm(X)。 (permutation) ➢(ri)perm(X)表示在全排列perm(X)的每一个排列前 加上前缀得到的排列。
22
➢由此可见,n个圆盘的移动问题可分为2次n-1个圆 盘的移动问题,这又可以递归地用上述方法来做。
解Hanoi塔问题的递归算法如下:
void hanoi(int n, int a, int b, int c) { if (n > 0) { hanoi(n-1, a, c, b); move(a,b); hanoi(n-1, c, b, a); } }
n1,m1 nm nm
计算机专业课《算法》_第二章 递归与分治策略

“Hanoi 塔”问题演示 a 初始 a 步骤1 a
c
b
c
“Hanoi 塔”问题程序
void hanoi(int n,a,b,c)
{ if n == 1 move( 1, a, b );
else { hanoi( n-1, a, c, b );
move(n, a, b ); hanoi( n-1, c,b, a) ;
• 递归优点:结构清晰,可读性强
• 递归缺点:递归算法的运行效率较低,无论是耗 费的计算时间还是占用的存储空间都比非递归算 法要多。
整数划分问题的递归关系q(n,m)
如设p(n)为正整数n的划分数,则难以找到递归关系 • q(n,m):正整数n的不同的划分中,最大加数不 大于m的划分个数个数 q(n,m)=
1 q(n,n) 1+q(n,n-1) q(n,m-1)+q(n-m,m) n=1, m=1 n<m n=m n>m>1
递归函数举例(5)
学习要点
理解递归的概念。 掌握设计有效算法的分治策略。
通过典型范例,学习分治策略设计技巧。
2.1 递归的概念
• 递归算法:一个直接或间接地调用自身的算法 • 递归方程:对于递归算法,一般可把时间代 价表示为一个递归方程 • 递归函数:使用函数自身给出定义的函数 • 解递归方程最常用的方法是进行递归扩展
递归函数举例(1)
• 阶乘函数 n !=
1 n(n-1)! n=1 n>1
• Fibonacci数列
1 n=0
F(n)=
1 F(n-1)+F(n-2)
n=1 n>1
初始条件与递归方程是递归函数的二个要素
第二章递归与分治

2019/3/24 计算机算法设计与分析 7
正整数的划分
在正整数的所有不同划分中,将最大加数n1不 大于m的划分个数记为q(n, m),可以建立如下 的递归关系: 的二元递归函数: n= 1 n, 或m m =1 q (n, m) { 1 (1) q(n, 1)=1, q(1, m) 最简单情形: =1 ≥1; q(n, m) = 1 + q(n, n –1) n ≤ m if (n < 1) || (m < 1) return 0; 递归关系: (2) q(n, n) = 1 + q(n, n–1),n>1; q(n, m– 1)+q(n –m, m) if (n == 1) || (m == 1) return 1; n>m>1 产生的新情况: if (n == 1) || (n < m) return 1 + q(n, n–1); return q(n, m –1) q(n m, } n>m>1 (3) q(n, m) =q (n, m+ –1) +–q (nm); –m, m), (4) q(n, m) = q(n, n),=n < mn) 。 整数 n的划分数 ρ(n) q (n, 。
2019/3/24 计算机算法设计与分析 3
Hanoi塔问题
例 Hanoi 1:Hanoi 塔的解可以很自然地看成这样一个过程: 塔问题:有A、B、C三根柱子。A
上有n个圆盘,自下而上由大到小地叠在一起。 于是可得到如下的程序: (1)先将A上面 现要将 A上的全部圆 n –1 个盘移至 C。 void Hanoi(int n, int Fr, int To, int As) { 盘移到B上,并要求: if (n > 0) { (2)再将 A上剩下 (1)每次只能移动一个 Hanoi(n–1, Fro, Ass, To); 的1 个盘移至 B。 圆盘; (2)任何时刻都 B C A Move(Fro, To); 不允许将较大的圆盘 Hanoi(n–1, Ass, To, Fro)} (3) 最后将C上的 压在较小的圆盘上; } n–(3) 1个盘移至 B。A、B、 圆盘只能在 C三个柱子间移动。
正整数的划分
在正整数的所有不同划分中,将最大加数n1不 大于m的划分个数记为q(n, m),可以建立如下 的递归关系: 的二元递归函数: n= 1 n, 或m m =1 q (n, m) { 1 (1) q(n, 1)=1, q(1, m) 最简单情形: =1 ≥1; q(n, m) = 1 + q(n, n –1) n ≤ m if (n < 1) || (m < 1) return 0; 递归关系: (2) q(n, n) = 1 + q(n, n–1),n>1; q(n, m– 1)+q(n –m, m) if (n == 1) || (m == 1) return 1; n>m>1 产生的新情况: if (n == 1) || (n < m) return 1 + q(n, n–1); return q(n, m –1) q(n m, } n>m>1 (3) q(n, m) =q (n, m+ –1) +–q (nm); –m, m), (4) q(n, m) = q(n, n),=n < mn) 。 整数 n的划分数 ρ(n) q (n, 。
2019/3/24 计算机算法设计与分析 3
Hanoi塔问题
例 Hanoi 1:Hanoi 塔的解可以很自然地看成这样一个过程: 塔问题:有A、B、C三根柱子。A
上有n个圆盘,自下而上由大到小地叠在一起。 于是可得到如下的程序: (1)先将A上面 现要将 A上的全部圆 n –1 个盘移至 C。 void Hanoi(int n, int Fr, int To, int As) { 盘移到B上,并要求: if (n > 0) { (2)再将 A上剩下 (1)每次只能移动一个 Hanoi(n–1, Fro, Ass, To); 的1 个盘移至 B。 圆盘; (2)任何时刻都 B C A Move(Fro, To); 不允许将较大的圆盘 Hanoi(n–1, Ass, To, Fro)} (3) 最后将C上的 压在较小的圆盘上; } n–(3) 1个盘移至 B。A、B、 圆盘只能在 C三个柱子间移动。
c02 递归与分治策略分解

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
算法总体思想
将求出的小规模的问题的解合并为一个更大规 模的问题的解,自底向上逐步求出原来问题的 解。
{ if (n <= 1) return 1; return fibonacci(n-1)+fibonacci(n-2);
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)二分搜索技术; (2)大整数乘法; 3)Strassen矩阵乘法; 4)棋盘覆盖; 5)合并排序和快速排序; 6)线性时间选择; (7)最接近点对问题; (8)循环赛日程表。
算法总体思想
2.1 递归的概念
直接或间接地调用自身的算法称为递归算法。 用函数自身给出定义的函数称为递归函数。
由分治法产生的子问题是原问题的较小模式, 为使用递归技术提供了方便。反复应用分治 手段,使子问题与原问题类型一致而其规模 却不断缩小,最终使子问题缩小到很容易直 接求出其解。这自然导致递归过程的产生。
递归与分治策略

7
例2-4 排列问题 Template<class type>
void Perm(Type list[ ], int k, int m)
{//Generate all permutations of list[k:m].
if (k==m) //第一版中有错误
{//list[k:m] has one permutation, output it
}
例2-2 Fibonacci数列
1
n=0 这两种递归可 转换为非递归
F(n)= 1
n=1 方式,但并不
F(n-1)+F(n-2) n>1 是全部递归都
int Fibonacci(int n)
能够转换。
{ if(n<=1) return 1;
return Fibonacci(n-1)+Fibonacci(n-2); }
q(n, n)=1+q(n, n-1) 若n>m>1,则 q(n, m)=q(n, m-1)+q(n-m, m)
10
例2-5 整数划分问题
int a(int n, int m) {
if((n<1) or (m<1)) return 0; if((n==1) or (m==1)) return 1; if(n<m) return q(n,n); if(n==m) return q(n,m-1)+1; return q(n,m-1)+q(n-m,m); }
第2章 递归与分治策略
Recursive divide-and-conquer strategy
• 了解递归旳概念 • 掌握设计有效算法旳分治策略 • 经过范例学习分治策略旳设计技巧
例2-4 排列问题 Template<class type>
void Perm(Type list[ ], int k, int m)
{//Generate all permutations of list[k:m].
if (k==m) //第一版中有错误
{//list[k:m] has one permutation, output it
}
例2-2 Fibonacci数列
1
n=0 这两种递归可 转换为非递归
F(n)= 1
n=1 方式,但并不
F(n-1)+F(n-2) n>1 是全部递归都
int Fibonacci(int n)
能够转换。
{ if(n<=1) return 1;
return Fibonacci(n-1)+Fibonacci(n-2); }
q(n, n)=1+q(n, n-1) 若n>m>1,则 q(n, m)=q(n, m-1)+q(n-m, m)
10
例2-5 整数划分问题
int a(int n, int m) {
if((n<1) or (m<1)) return 0; if((n==1) or (m==1)) return 1; if(n<m) return q(n,n); if(n==m) return q(n,m-1)+1; return q(n,m-1)+q(n-m,m); }
第2章 递归与分治策略
Recursive divide-and-conquer strategy
• 了解递归旳概念 • 掌握设计有效算法旳分治策略 • 经过范例学习分治策略旳设计技巧
第2章 递归与分治策略优秀课件

第2章 递归与分治策 略
以Rk( c ) 记放k个车的不同放法,令R0( c ) = 1 上面的棋盘C的棋盘多项式等于:
R( c )=1+n2x+
(
n
2
)2x2
+……+
(
n
r
)2
+n!xn
但是,我们经常碰到的是不完整的棋盘,这类棋盘 称残缺棋盘。
R( )= 1+X
R(
R ( ) = R ( ) = 1+2X R(
1 2 3 45
a
b c
d
e
(1+3X+X2) (1+4X+3X2)
正交的相乘
R(C)= (1+3X+X2)*(1+4X+3X2) = 1+7X+16X2+13X3+3X4
对照得到: B(0)= 5!- 7*4!+16*3!-13*2!+3*1!+ 0
= 25
这是简单的棋盘多项式能解决的问题,如果 有不正交的情况,我们主要采用下面的方法 进行构造。
) = 1+3X+X2 ) = 1+2X+X2 = (1+X)2
R ( ) = 1+4X+2X2
R(
) = 1+6X+7X2+X3
下面我们看一些应用: example: 在a,b,c,d,e的全排列中,要求a不出现在 第1和第5位,b不出现在第2和第3位,c不出现在 第3和第4位,e不出现在第5位,问:满足这些要 求的全排列有多少?
设所有元素互不相同。在这种情况下,找 出的基准x至少比3(n-5)/10个元素大,因为在 每一组中有2个元素小于本组的中位数,而 n/5个中位数中又有(n-5)/10个小于基准x。同 理,基准x也至少比3(n-5)/10个元素小。而当 n≥75时,3(n-5)/10≥n/4所以按此基准划分所 得的2个子数组的长度都至少缩短1/4。
以Rk( c ) 记放k个车的不同放法,令R0( c ) = 1 上面的棋盘C的棋盘多项式等于:
R( c )=1+n2x+
(
n
2
)2x2
+……+
(
n
r
)2
+n!xn
但是,我们经常碰到的是不完整的棋盘,这类棋盘 称残缺棋盘。
R( )= 1+X
R(
R ( ) = R ( ) = 1+2X R(
1 2 3 45
a
b c
d
e
(1+3X+X2) (1+4X+3X2)
正交的相乘
R(C)= (1+3X+X2)*(1+4X+3X2) = 1+7X+16X2+13X3+3X4
对照得到: B(0)= 5!- 7*4!+16*3!-13*2!+3*1!+ 0
= 25
这是简单的棋盘多项式能解决的问题,如果 有不正交的情况,我们主要采用下面的方法 进行构造。
) = 1+3X+X2 ) = 1+2X+X2 = (1+X)2
R ( ) = 1+4X+2X2
R(
) = 1+6X+7X2+X3
下面我们看一些应用: example: 在a,b,c,d,e的全排列中,要求a不出现在 第1和第5位,b不出现在第2和第3位,c不出现在 第3和第4位,e不出现在第5位,问:满足这些要 求的全排列有多少?
设所有元素互不相同。在这种情况下,找 出的基准x至少比3(n-5)/10个元素大,因为在 每一组中有2个元素小于本组的中位数,而 n/5个中位数中又有(n-5)/10个小于基准x。同 理,基准x也至少比3(n-5)/10个元素小。而当 n≥75时,3(n-5)/10≥n/4所以按此基准划分所 得的2个子数组的长度都至少缩短1/4。
第2章递归与分治策略

说明:边界条件与递归方程是递归函数的两个要素, 递归函数只有具备了这两个要素,才能在有限次计
算后得出结果。
2024/7/30
算法设计与分析
4
递归函数的内部执行过程
递归函数内部执行过程如下:
(1)运行开始时,为递归调用建立一个工作栈,其结 构包括实参、局部变量和返回地址;
(2)每次执行递归调用之前,把递归函数的实参和局 部变量的当前值以及调用后的返回地址压栈;
• Ackerman函数A(n, m)定义如下,n, m是两个独 立的整变量,其中n, m均≥0:
A1,0 2
A0, m 1
An,0 n 2
An, m AAn 1, m, m 1
m0 n2 n, m 1
2024/7/30
算法设计与分析
8
分析
• A(n,m)的自变量m的每一个值都定义了一个单 变量函数:
– 将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
2024/7/30
算法设计与分析
25
原问题 的规模是n
子问题1 的规模是n/2
子问题2 的规模是n/2
子问题1的解
子问题2的解
原问题的解
2024/7/30
算法设计与分析
26
问题(N个输入)
合 子问题1 并 解
(3)每次递归调用结束后,将栈顶元素出栈,使相应 的实参和局部变量恢复为调用前的值,然后转向返回地 址指定的位置继续执行
举例2-2:Fibonacci数列
• 无穷数列1, 1, 2, 3, 5, 8, 13, 21, 34, 55,…,被称
为Fibonacci数列。 • 它可以递归定义为:
2、递归与分治策略

例4
Hanoi塔问题 Hanoi塔问题
在问题规模较大时,较难找到一般的方法,因此我们尝试 用递归技术来解决这个问题。 当n=1时,问题比较简单。此时,只要将编号为1的圆盘从 塔座a直接移至塔座b上即可。 当n>1时,需要利用塔座c作为辅助塔座。此时若能设法 将n-1个较小的圆盘依照移动规则从塔座a移至塔座c,然 后,将剩下的最大圆盘从塔座a移至塔座b,最后,再设法 将n-1个较小的圆盘依照移动规则从塔座c移至塔座b。 由此可见,n个圆盘的移动问题可分为2次n-1个圆盘的移 动问题,这又可以递归地用上述方法来做。由此可以设计 出解Hanoi塔问题的递归算法如下。
将求出的小规模的问题的解合并为一个更大规模的问题 的解,自底向上逐步求出原来问题的解。
T(n)
n/2
=
n
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/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/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)
第n个Fibonacci数可递归地计算如下: public static int fibonacci(int n) { if (n <= 1) return 1; return fibonacci(n-1)+fibonacci(n-2); }
前2例中的函数都可以找到相应的非递归方式定义:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
分治法的一般算法
• 分治法的一般的算法模式为:
• Divide-and-Conquer(P) • {//|P|<=n0表示P的规模不超过阈值n0,可直接求解 • if (|P|<=n0) return Adhoc(P); • divide P into smaller subinstants P1, .., Pk; • for (i =1; i <= k; i++) • yi = Divide-and-Conquer(Pi); • return Merge(y1, …, yk); • } //算法Merge(y1, …, yk)表示将子问题的解合成P的解 人们从大量实践中发现,在用分治法设计算法时, 最好使子问题的规模大致相同。即将一个问题分成 大小相等的k个子问题的处理方法是行之有效的。 这种使子问题规模大致相等的做法是出自一种平衡 (balancing)子问题的思想,它几乎总是比子问题 20 规模不等的做法要好。
22
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。 分析: 该问题的规模缩小到一定的程度就可以容易地解决; 该问题可以分解为若干个规模较小的相同问题; 分解出的子问题的解可以合并为原问题的解; 分解出的各个子问题是相互独立的。 分析:比较x和a的中间元素a[mid],若x=a[mid],则x在L中的 位置就是mid;如果x<a[mid],由于a是递增排序的,因此假 分析:如果n=1即只有一个元素,则只要比较这个元素和x就 分析:很显然此问题分解出的子问题相互独立,即在a[i]的前 如x在a中的话,x必然排在a[mid]的前面,所以我们只要在 可以确定x是否在表中。因此这个问题满足分治法的第一个适 面或后面查找x是独立的子问题,因此满足分治法的第四个适 a[mid]的前面查找x即可;如果x>a[i],同理我们只要在a[mid] 用条件 用条件。 的后面查找x即可。无论是在前面还是后面查找x,其方法都 和在a中查找x一样,只不过是查找的规模缩小了。这就说明 了此问题满足分治法的第二个和第三个适用条件。
P if B then Q else β(S, P)
其中Q也不包含P,B为递归终止条件。
3
递归元
• 递归算法的思想是将对较大规模的对象的操作 归结为对较小规模的对象实施同样的操作。 • 这种规模的变化就体现在递归算法的变元中的 一类(一个或几个)变元上,这类变元被称之为 递归元。 • 递归元的变化是在递归定义中确定的,它的变 化应能导致递归算法的终止。 • 在递归算法的设计中递归元是非常重要的。
• 正整数n的一个这种表示称为正整数n的一个 例如ρ(6) = 11 ,即整数6的划分数为11种: 6, 5+1, 4+2, 4+1+1, 3+3, 3+2+1, 3+1+1+1 划分。正整数n的不同的划分的个数成为正整 数n的划分数,记作ρ(n)。 2+2+2, 2+2+1+1, 2+1+1+1+1, 1+1+1+1+1+1
14
分治法
15
算法总体思想
• 对这k个子问题分别求解。如果子问题的规模仍然不够 •小,则再划分为k个子问题,如此递归的进行下去,直 将要求解的较大规模的问题分割成k个更小规模的 子问题。 到问题规模足够小,很容易求出其解为止。
T(n)
=
n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
16
算法总体思想
• 递归算法是有层次的,低层子问题的解组合成 高层问题的解。各层之间最好通过参数传递来 交流信息,如使用全局量,则要注意全局量的 及时修订。
12
递归小结
优点:结构清晰,可读性强,而且容易用 数学归纳法来证明算法的正确性,因此它 为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是 耗费的计算时间还是占用的存储空间都比 非递归算法要多。
13
递归小结
解决方法:在递归算法中消除递归调用,使其转化为 非递归算法。 1、采用一个用户定义的栈来模拟系统的递归调用工作 栈。该方法通用性强,但本质上还是递归,只不过人 工做了本来由编译器做的事情,优化效果不明显。 2、用递推来实现递归函数。 3、通过变换能将一些递归转化为尾递归,从而迭代求 出结果。 后两种方法在时空复杂度上均有较大改善,但其 适用范围有限。
• 将求出的小规模的问题的解合并为一个更大规模的问 • 对这k个子问题分别求解。如果子问题的规模仍然不够 题的解,自底向上逐步求出原来问题的解。 小,则再划分为k个子问题,如此递归的进行下去,直 到问题规模足够小,很容易求出其解为止。
T(n)
n/2
=
n/2
n
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 17
4
常见的递归形式
• 除基本的递归形式外,其它常见的递归 形式有四种,它们是: • 多变元递归; • 多步递归; • 嵌套递归; • 联立递归
5
多变元递归
•• 多变元递归就是递归元多于一个的递归。 例2:整数划分问题:将一个正整数n表示为 一系列正整数之和, n = n1 + n2 +…+nk 其中n1≥n2≥…≥nk≥1, k≥1。
第二章
递归与分治策略
1
• 例1:Hanoi塔问题:有A、B、C三根柱子。A Hanoi塔的解可以很自然地看成这样一个过程: 上有n个圆盘,自下而上由大到小地叠在一起。
于是可得到如下的程序: (1)先将A上面n–1 现要将A上的全部圆 void Hanoi(int n, int Fr, int To, int As) 个盘移至C。 盘移到B上,并要求: { (2)再将A上剩下的 (1)每次只能移动一个 if (n > 0) { 1个盘移至B。 圆盘;(2)任何时刻都 Hanoi(n–1, Fro, Ass, To); B C A 不允许将较大的圆盘 Move(Fro, To); (3)最后将C上的n– 压在较小的圆盘上; Hanoi(n–1, Ass, To, Fro)} 1个盘移至B。 (3)圆盘只能在A、B、 }
分治法的时间复杂性
• 分治法的时间复杂性为: O(1) n=1 T(n) ≤ kT(n/m) + f(n) n>1 其中设子问题规模为n/m,Merge的时间为f(n)。
求解此递归方程可得:
T(n) ≤ n logmk + ∑ kjf(n/mj)
j=0
logmn–1
21
分治法的适用条件
分治法所能解决的问题一般具有以下几个特征:
6
正整数的划分
• 有时候,问题本身具有比较明显的递归 关系,因而容易用递归函数直接求解。 • 在本例中,如果设p(n)为正整数n的划分 数,则难以直接找到递归关系。
7
正整数的划分
• 因此考虑增加一个自变量:在正整数的所有 不同划分中,将最大加数n1不大于m的划分个 m),可以建立如下的递归关系: 数记为q(n, m),可以建立如下的二元递归函数: 1 n = 1 n, m≥1; • int q(int n, int m) q(n, 1)=1,q(1, m) =1或 m = 1 最简单情形:(1) { m) = 1 + q(n, n–1) q(n, n≤m • 递归关系: (2) q(n, n) = 1 + q(n, n–1),n>1; if (n < 1) q(n, m–1)+q(n–m, m) n>m>1 || (m < 1) return 0; • 产生的新情况: == 1) return 1; if (n == 1) || (m if(n < • (3) q(n, m) return q(n, n); q(n–m, m), n>m>1 = q(n, m–1) + if (n == m) return 1 + q(n, n–1); • (4) q(n, m) = q(n, n), n<m。 return q(n, m–1) + q(n–m, m); }
算法总体思想
• 将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是,将一个难以直接解决的大问题, n = T(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 19
Hanoi塔问题
C三个柱子间移动。
2
递归的概念
• 简单地说,递归就是用自己来定义自己。递归 算法是一个直接或间接地调用自己的算法。 • 一般地说,一个递归过程P可以表示为基语句 S(不含P)和P自身的组合β:
P β(S, P)
• 这样的表示包含了过程不终止的可能,因此递 归算法应更准确地表述为
}
return -1; }
算法复杂度分析: 每执行一次算法的while循环, 待 搜索数组的大小减少一半。因此, 在最坏情况下,while循环被执行了 O(logn) 次。循环体内运算需要O(1) 时间,因此整个算法在最坏情况下 的计算时间复杂性为O(logn) 。 24
9
嵌套递归
• 所谓嵌套递归是指递归调用中又含有递归调用, 又称为多重递归。 • 例如Ackermann函数: