函数的递归调用与分治策略
递归与分治算法心得

递归与分治算法心得
递归与分治算法都是常用的算法思想,可以很好地解决复杂问题。
递归算法是通过将问题分解为相同或相似的子问题来解决整个问题,然后再逐步合并回原问题的过程。
递归算法通常需要明确边界条件,以确保递归能够正确地停止。
分治算法是将问题分解成若干个相同或相似的子问题,递归地解决这些子问题,然后合并这些子问题的解来解决原始问题。
通常,分治算法可以高效地解决问题,但需要注意分解问题的方式和合并子问题的解的过程。
在实际应用中,递归和分治算法可以相互结合,以解决更加复杂的问题。
例如,可以使用分治算法来将问题分解成多个子问题,然后使用递归算法来解决这些子问题。
此外,还可以在递归算法中使用分治算法来对子问题进行分解和合并。
总而言之,递归与分治算法都是非常有用的算法思想,可以在许多领域中得到应用。
但是,在实际使用时,需要仔细考虑问题的性质和算法的复杂度,以确保算法的正确性和效率。
- 1 -。
递归与分治算法心得

递归与分治算法心得
递归与分治算法是算法设计中常见的两种方法,它们在解决问题时都采用了“分而治之”的思想,将问题分解成更小的子问题,然后通过递归调用或者合并子问题的解来得到原问题的解。
通过我的学习和实践,我深刻认识到了递归与分治算法的重要性和优势。
首先,递归算法可以使问题的描述更加简单明了。
通过将问题转化为自身的子问题,我们可以建立起更为简洁优美的数学模型。
其次,递归算法可以使问题的解决过程更加自然。
在递归过程中,我们可以利用已知的子问题解决同类问题,实现代码的复用和模块化。
此外,递归算法还可以解决一些重要的数学问题,如斐波那契数列和二分查找等。
分治算法则更加注重问题的分解和合并。
它将问题划分成若干个规模相同或相近的子问题,然后将子问题的解合并起来得到原问题的解。
这种方法在解决某些复杂问题时具有很大的优势。
例如,在排序算法中,归并排序采用了分治算法的思想,将待排序的序列分成两个长度相等的子序列,然后递归地对子序列排序,最后将子序列合并成有序序列。
这种算法具有较高的稳定性和灵活性,常常被应用于海量数据的排序任务中。
总之,递归与分治算法是算法设计中不可或缺的两种方法。
在解决问题时,我们应该根据具体情况选择合适的算法,并在实践中不断探索、总结和优化。
只有这样,我们才能更好地应对日益复杂多变的计算机科学挑战。
递归和分治法

递归和分治法摘要:1.递归和分治法的定义2.递归和分治法的区别3.递归和分治法的应用实例4.递归和分治法的优缺点正文:递归和分治法是计算机科学中常用的两种算法设计技巧。
它们在解决问题时都采用了将问题分解成更小子问题的思路,但在具体实现上却有所不同。
下面,我们来详细了解一下递归和分治法。
1.递归和分治法的定义递归法是指在算法中调用自身来解决问题的方法。
递归函数在执行过程中,会将原问题分解成规模更小的相似子问题,然后通过调用自身的方式,解决这些子问题,最后将子问题的解合并,得到原问题的解。
分治法是指将一个大问题分解成若干个规模较小的相似子问题,然后分别解决这些子问题,最后将子问题的解合并,得到原问题的解。
分治法在解决问题时,通常需要设计一个主函数(master function)和一个子函数(subfunction)。
主函数负责将问题分解,子函数负责解决子问题。
2.递归和分治法的区别递归法和分治法在解决问题时都采用了将问题分解成更小子问题的思路,但它们在实现上存在以下区别:(1)函数调用方式不同:递归法是通过调用自身来解决问题,而分治法是通过调用不同的子函数来解决问题。
(2)递归法必须有递归出口,即必须有一个基线条件,而分治法不一定需要。
3.递归和分治法的应用实例递归法应用广泛,例如斐波那契数列、汉诺塔问题、八皇后问题等。
分治法也有很多实际应用,例如快速排序、归并排序、大整数乘法等。
4.递归和分治法的优缺点递归法的优点是代码简单易懂,但缺点是容易产生大量的重复计算,导致时间复杂度较高。
分治法的优点是时间复杂度较低,但缺点是代码实现相对复杂,需要设计主函数和子函数。
总之,递归和分治法都是解决问题的有效方法,具体应用需要根据问题的特点来选择。
必备算法:递归!无论你是前端开发,还是后端开发,都需要掌握它!

必备算法:递归!⽆论你是前端开发,还是后端开发,都需要掌握它!递归是⼀种⾮常重要的算法思想,⽆论你是前端开发,还是后端开发,都需要掌握它。
在⽇常⼯作中,统计⽂件夹⼤⼩,解析xml⽂件等等,都需要⽤到递归算法。
它太基础太重要了,这也是为什么⾯试的时候,⾯试官经常让我们⼿写递归算法。
本⽂呢,将跟⼤家⼀起深⼊挖掘⼀下递归算法~什么是递归?递归,在计算机科学中是指⼀种通过重复将问题分解为同类的⼦问题⽽解决问题的⽅法。
简单来说,递归表现为函数调⽤函数本⾝。
在知乎看到⼀个⽐喻递归的例⼦,个⼈觉得⾮常形象,⼤家看⼀下:❝递归最恰当的⽐喻,就是查词典。
我们使⽤的词典,本⾝就是递归,为了解释⼀个词,需要使⽤更多的词。
当你查⼀个词,发现这个词的解释中某个词仍然不懂,于是你开始查这第⼆个词,可惜,第⼆个词⾥仍然有不懂的词,于是查第三个词,这样查下去,直到有⼀个词的解释是你完全能看懂的,那么递归⾛到了尽头,然后你开始后退,逐个明⽩之前查过的每⼀个词,最终,你明⽩了最开始那个词的意思。
❞来试试⽔,看⼀个递归的代码例⼦吧,如下:递归的特点实际上,递归有两个显著的特征,终⽌条件和⾃⾝调⽤:✿⾃⾝调⽤:原问题可以分解为⼦问题,⼦问题和原问题的求解⽅法是⼀致的,即都是调⽤⾃⾝的同⼀个函数。
✿终⽌条件:递归必须有⼀个终⽌的条件,即不能⽆限循环地调⽤本⾝。
结合以上demo代码例⼦,看下递归的特点:递归与栈的关系其实,递归的过程,可以理解为出⼊栈的过程的,这个⽐喻呢,只是为了⽅便读者朋友更好理解递归哈。
以上代码例⼦计算sum(n=3)的出⼊栈图如下:为了更容易理解⼀些,我们来看⼀下函数sum(n=5)的递归执⾏过程,如下:✿计算sum(5)时,先sum(5)⼊栈,然后原问题sum(5)拆分为⼦问题sum(4),再⼊栈,直到终⽌条件sum(n=1)=1,就开始出栈。
✿ sum(1)出栈后,sum(2)开始出栈,接着sum(3)。
✿最后呢,sum(1)就是后进先出,sum(5)是先进后出,因此递归过程可以理解为栈出⼊过程啦~递归的经典应⽤场景哪些问题我们可以考虑使⽤递归来解决呢?即递归的应⽤场景⼀般有哪些呢?✿阶乘问题✿⼆叉树深度✿汉诺塔问题✿斐波那契数列✿快速排序、归并排序(分治算法体现递归)✿遍历⽂件,解析xml⽂件递归解题思路解决递归问题⼀般就三步曲,分别是:✿第⼀步,定义函数功能✿第⼆步,寻找递归终⽌条件✿第⼆步,递推函数的等价关系式这个递归解题三板斧理解起来有点抽象,我们拿阶乘递归例⼦来喵喵吧~1、定义函数功能定义函数功能,就是说,你这个函数是⼲嘛的,做什么事情,换句话说,你要知道递归原问题是什么呀?⽐如你需要解决阶乘问题,定义的函数功能就是n的阶乘,如下:2、寻找递归终⽌条件递归的⼀个典型特征就是必须有⼀个终⽌的条件,即不能⽆限循环地调⽤本⾝。
matlab function 递归函数

MATLAB递归函数1. 引言MATLAB是一种功能强大的数值计算和科学编程语言,具有丰富的函数库和工具箱。
递归函数是一种特殊类型的函数,它在函数体内调用自身。
递归函数在解决一些复杂问题时非常有用,可以将一个大问题分解成一个或多个更小的子问题进行求解。
本文将详细介绍MATLAB递归函数的定义、用途和工作方式,以及如何编写递归函数来解决实际问题。
2. 函数的定义递归函数是一种在函数体内调用自身的函数。
它可以通过将一个问题分解成更小的子问题来解决复杂的问题。
递归函数通常具有以下几个要素:•基本情况(Base case):递归函数必须包含一个或多个基本情况,即函数不再调用自身的情况。
基本情况通常是一个简单的问题,可以直接求解而不需要进一步的递归调用。
•递归调用(Recursive call):递归函数在函数体内调用自身,并将问题规模缩小为一个或多个子问题。
递归调用通常在某个条件满足时发生,否则函数将陷入无限循环。
•问题规模缩减(Problem reduction):递归函数通过将一个大问题分解成一个或多个更小的子问题来解决复杂的问题。
每次递归调用都会将问题的规模缩小,直到达到基本情况。
3. 递归函数的用途递归函数在解决一些复杂问题时非常有用,特别是那些可以通过将问题分解成更小的子问题来解决的情况。
递归函数的用途包括但不限于以下几个方面:•分治法(Divide and conquer):递归函数可以将一个大问题分解成一个或多个更小的子问题,并将子问题的解合并成原问题的解。
分治法通常用于解决一些需要分解成子问题的问题,例如排序、搜索和图算法等。
•树和图的遍历:递归函数可以用于树和图的遍历,例如深度优先搜索(DFS)和广度优先搜索(BFS)。
递归函数可以通过递归调用来遍历树和图的节点,并在每个节点上执行相应的操作。
•动态规划:递归函数在动态规划中也经常被使用。
动态规划是一种通过将问题分解成更小的子问题来求解的优化技术。
递归算法思路

递归算法思路一、概念递归算法是指函数自身调用自身的方法,将一个问题分解为更小的同类问题直到问题简单到可以直接解决。
递归算法是由一种表达方式所实现的,这种表达方式就是递归定义。
二、递归算法的思路(1)确定递归函数的参数和返回值确定参数和返回值的关键是看待问题的方法。
递归函数所处理的问题应该是可以分解为若干个子问题的,而这些子问题其实就是原问题的缩小范围。
(2)递归边界问题在递归函数中,我们必须要规定好对应的递归边界,也就是终止条件。
如果没有递归边界,那么整个递归链式结构将不断进行推进,直到系统无法承受,连程序都无法正常运行。
(3)将原问题分解为更小的子问题我们需要在递归函数中对原问题进行分解,即将原问题转化为若干个子问题。
这些子问题与原问题是同类问题,由于子问题的规模比原问题更小,我们可以通过解决子问题来解决原问题。
(4)进行递归调用确定好递归边界和子问题之后,就可以通过递归调用将问题规模不断缩小,使得问题最终可以直接得到解决。
(5)整合所有递归的结果递归算法的最后一步是整合所有递归的结果,将其合并为一个完整的解决方案。
这可能需要对递归结果进行一些计算和转换,然后将它们组合在一起形成最终结果。
三、递归算法的优缺点(1)优点递归算法可以清晰地表达问题的递归结构,很容易理解和实现。
对于复杂的问题,递归算法往往比起迭代算法更具可读性。
同时,递归算法还可以缩小问题的规模,使问题的求解更为高效。
(2)缺点递归算法的缺点在于它可能导致许多不必要的重复计算,这样会大大降低算法的效率。
此外,在调用函数时,需要保存参数、返回值和局部变量等一些额外的信息,这些信息都需要分配内存并占用空间。
当递归调用太深时,可能会引起严重的栈溢出问题。
四、递归算法的应用(1)数学问题递归算法常常在解决数学问题时得到应用。
例如,斐波那契数列、阶乘问题、最大公约数和最小公倍数问题等,都可以通过递归算法来解决。
(2)树形问题当我们需要处理树形问题时,递归算法也可以起到很好的作用。
算法设计与分析:递归与分治法-实验报告(总8页)

算法设计与分析:递归与分治法-实验报告(总8页)实验目的:掌握递归与分治法的基本思想和应用,学会设计和实现递归算法和分治算法,能够分析和评价算法的时间复杂度和空间复杂度。
实验内容:1.递归算法的设计与实现3.算法的时间复杂度和空间复杂度分析实验步骤:1)递归定义:一个函数或过程,在其定义或实现中,直接或间接地调用自身的方法,被成为递归。
递归算法是一种控制结构,它包含了解决问题的基础情境,也包含了递归处理的情境。
2)递归特点:递归算法具有以下特点:①依赖于递归问题的部分解被划分为若干较小的部分。
②问题的规模可以通过递推式递减,最终递归终止。
③当问题的规模足够小时,可以直接求解。
3)递归实现步骤:①确定函数的定义②确定递归终止条件③确定递归调用的过程4)经典实例:斐波那契数列递推式:f(n) = f(n-1) + f(n-2)int fib(int n) {if (n <= 0)return 0;else}5)优化递归算法:避免重复计算例如,上述斐波那契数列的递归算法会重复计算一些中间结果,影响效率。
可以使用动态规划技术,将算法改为非递归形式。
int f1 = 0, f2 = 1;for (int i = 2; i <= n; i++) {f1 = f2;使用循环避免递归,重复计算可以大大减少,提高效率。
1)分治算法的定义:将原问题分解成若干个规模较小且类似的子问题,递归求解子问题,然后合并各子问题得到原问题的解。
2)分治算法流程:②将问题分解成若干个规模较小的子问题。
③递归地解决各子问题。
④将各子问题的解合并成原问题的解。
3)分治算法实例:归并排序归并排序是一种基于分治思想的经典排序算法。
排序流程:②分别对各子数组递归进行归并排序。
③将已经排序好的各子数组合并成最终的排序结果。
实现源代码:void mergeSort(int* arr, int left, int right) {if (left >= right)while (i <= mid && j <= right)temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];temp[k++] = arr[i++];1) 时间复杂度的概念:指完成算法所需的计算次数或操作次数。
计算机专业课《算法》_第二章 递归与分治策略

“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
初始条件与递归方程是递归函数的二个要素
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
函数的递归调用与分治策
略
This manuscript was revised on November 28, 2020
函数的递归调用与分治策略
递归方法是算法和程序设计中的一种重要技术。
递归方法即通过函数或过程调用自身将问题转化为本质相同但规模较小的子问题。
递归方法具有易于描述和理解、证明简单等优点,在动态规划、贪心算法、回溯法等诸多算法中都有着极为广泛的应用,是许多复杂算法的基础。
递归方法中所使用的“分而治之”的策略也称分治策略。
递归方法的构造
构造递归方法的关键在于建立递归关系。
这里的递归关系可以是递归描述的,也可以是递推描述的。
下面由一个求n的阶乘的程序为例,总结出构造递归方法的一般步骤。
[例1]从键盘输入正整数N(0<=N<=20),输出N!。
[分析]N!的计算是一个典型的递归问题。
使用递归方法来描述程序,十分简单且易于理解。
[步骤1]描述递归关系递归关系是这样的一种关系。
设{U1,U2,U3,…,Un…}是一个序列,如果从某一项k开始,Un和它之前的若干项之间存在一种只与n有关的关系,这便称为递归关系。
注意到,当N>=1时,N!=N*(N-1)!(N=1时,0!=1),这就是一种递归关系。
对于特定的K!,它只与K与(K-1)!有关。
[步骤2]确定递归边界在步骤1的递归关系中,对大于k的Un的求解将最终归结为对Uk的求解。
这里的Uk称为递归边界(或递归出口)。
在本例中,递归边界为k=0,即0!=1。
对于任意给定的N!,程序将最终求解到0!。
确定递归边界十分重要,如果没有确定递归边界,将导致程序无限递归而引起死
循环。
例如以下程序:
#include <>
int f(int x){
return(f(x-1));
}
main(){
cout<<f(10);
}
它没有规定递归边界,运行时将无限循环,会导致错误。
[步骤3]写出递归函数并译为代码将步骤1和步骤2中的递归关系与边界统一起来用数学语言来表示,即
N*(N-1)! 当N>=1时
n!=
1 当N=0时
再将这种关系翻译为代码,即一个函数:
long f(int n){
if (n==0)
return(1);
else
return(n*f(n-1));
}
[步骤4]完善程序主要的递归函数已经完成,将程序依题意补充完整即可。
ey>
j--;
if(i<j)
{
R[i]=R[j];
i++;
}
while( i<j&&R[i].key<
i++;
if(i<j)
{
R[j]=R[i];
j--;
}
}
R[i]=temp;
QuickSort(R,s,i-1);
QuickSort(R,i+1,t);
}
}
[例6]“九宫阵”智力游戏。
[问题描述]一个9×9方阵,由9个“九宫格”组成,每个九宫格又由3×3共9
个小格子组成。
请在每个空白小格子里面填上1~9的数字,使每个数字在每个九宫格内以及在整个九宫阵中的每行、每列上均出现一次。
(1)编程将下面图中的九宫阵补充完整。
(2)讨论是否可能给出“九宫阵”的全部解
[分析]本题可利用回溯法解决,其基本思想为深度优先搜索(DFS),这也是一种以分治策略为基础的算法。
回溯法与纯粹的DFS不同的是,它在搜索过程中不断杀死不合题意的结点。
这一点保证了解法的效率。
首先考虑如何得出全部解的情况。
解空间树容易构造,只需按顺序(从第一行第一个数字开始到第一行最后一个,然后第二行……,一直到最后一行最后一个数字)“尝试”填入数字即可。
为了解决这个问题,我们需要先编写一个函数check,其原型为int check(int i,int j,int k),用于求第i行第j列能否填上数字k。
如果可以,返回1,否则返回0。
由于我们是按顺序填入数字的,看起来一个数字后面的数字并不在判断能否填的范围内。
但为了解决题中某个特解问题的方便,还是引入较为严谨的判断方法。
函数check代码如下:
int check(int i,int j,int k){
int l,m,pi,pj;
Check the line
for (l=1;l<=9;l++)
if ( (l!=j) && (a[i][l]!=0) && (a[i][l]==k) )
return(0);
Check the column
for (l=1;l<=9;l++)
if ( (l!=i) && (a[l][j]!=0) && (a[l][j]==k) )
return(0);
Check the 3x3 matrix
Check the line
for (l=1;l<=9;l++)
if ( (l!=j) && (a[i][l]!=0) && (a[i][l]==k) )
return(0);
Check the column
for (l=1;l<=9;l++)
if ( (l!=i) && (a[l][j]!=0) && (a[l][j]==k) )
return(0);
Check the 3x3 matrix
// Firstly we will have to check the parent_i(pi) and parent_j(pj) if (i<=3) pi=1;
else if (i<=6) pi=4;
else pi=7;
if (j<=3) pj=1;
else if (j<=6) pj=4;
else pj=7;
// Now we can check it
for (l=0;l<=2;l++)
for (m=0;m<=2;m++){
if ( ((pi+l)!=i) && ((pj+m)!=j) )
if ( ( a[pi+l][pj+m]!=0 ) && ( a[pi+l][pj+m]==k ) ) return(0);
}
return(1);
}
void output(){
int i,j;
cout<<"One solution is:"<<endl;
for (i=1;i<=9;i++)
{
for (j=1;j<=9;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
}
void backtrack(int i,int j,int k){
int l;
if (check(i,j,k)==1)
{
a[i][j]=k; //Fill in the okay solution
//Generate next i,j
do{
if (j<9) j++;
else { i++; j=1; }
} while (a[i][j]!=0); //End of Generate next i,j
if (i<10)
{
for (l=1;l<=9;l++)
backtrack(i,j,l);
}
else
output();
a[i][j]=0; /*When fails and goes upperwards, the value must be cleared*/
}
}
void init(){
a[1][2]=9; a[1][6]=4; a[1][7]=5; a[1][9]=7;
a[2][3]=3; a[2][5]=7; a[2][6]=9; a[2][7]=4;
a[3][4]=3; a[3][5]=6; a[3][8]=8; a[3][9]=9;
a[4][1]=3; a[4][4]=1;
a[5][3]=4; a[5][8]=2; a[5][9]=3;
a[6][2]=1; a[6][3]=2; a[6][6]=3;
a[7][1]=8; a[7][8]=5;
a[8][2]=6; a[8][4]=2; a[8][5]=9;
a[9][2]=2; a[9][3]=1; a[9][7]=8;
//memset(a,0,sizeof(a));
}
int main(){
int i;
for (i=1;i<=9;i++){
init();
backtrack(1,1,i);
}
system("PAUSE");
return 0;
}
递归方法在算法与数据结构中的应用无所不在,如动态规划(状态方程)、回溯法(深度优先搜索)等等,以上两例只是冰山一角。
只有熟悉掌握函数递归调用的编程方法,深入理解分治策略的重要思想,才能编写出功能强大、高效简明的程序。