递归算法包括,一个递归算法必须包括()。
递归算法包括,一个递归算法必须包括()。详细介绍
本文目录一览: 一个递归算法必须包括什么?
递归算法包含的两个部分:
1、由其自身定义的与原始问题类似的更小规模的子问题(只有数据规模不同),它使递归过程持续进行,称为一般条件。
2、所描述问题的最简单的情况,它是一个能控制递归过程结束的条件,称为基本条件。(递归出口)
递归的定义:
如果一个对象部分地由它自身组成或按它自己定义,则称它是递归的,所以说递归就是函数/过程/子过程在运行过程中直接或间接调用自身而产生的重入现象。
递归的基本思想:
就是把一个规模大的问题分为若干个规模较小的子问题求解,而每一个子问题又可以分为几个规模更小的子问题。基本上,所有的递归问题都可以用递推公式来表示。
最重要的一点就是假设子问题已经解决了,现在要基于已经解决的子问题来解决当前问题;或者说,必须先解决子问题,再基于子问题来解决当前问题或者可以这么理解:递归解决的是有依赖顺序关系的多个问题。
递归的优缺点:
优点:逻辑清楚,结构清晰,可读性好,代码简洁,效率高(拓展:DFS深度优先搜素,前中后序二叉树遍历)
缺点:函数调用开销大,空间复杂度高,有堆栈溢出的风险
一个递归算法必须包括什么
一个递归算法必须包括终止条件和递归部分。递归算法(英语:recursionalgorithm)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。递归算法(英语:recursionalgorithm)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。
一个递归算法必须包括()。
一个递归算法必须包括()。
A.递归体
B.递归条件和递归体
C.迭代部分
D.终止条件和迭代部分
正确答案:递归条件和递归体
一个递归算法必须包括什么?
一个递归算法必须包括终止条件和递归部分。
一般循环就是:
int multi = 1;
if (x <=1) return (1);
for(int i=1;i<=x;i++)multi = multi*i;
return(multi);
递归把x!看作x*(x-1)!
int multi(int x){if(x==0||x==1) return 1;else return x*multi(x-1);}
尾部递归:
而不对其再加运算。尾部递归与循环是等价的,而且在一些语言(如Scheme中)可以被优化为循环指令。
在这些语言中尾部递归不会占用调用堆栈空间。以下Scheme程序同样计算一个数字的阶乘,但是使用尾部递归:(define (factorial n) (define (iter product counter) (if (> counter n) product (iter (* counter product) (+ counter 1)))) (iter 1 1))。
什么是递归算法??
递归算法是一种使用递归的计算方法,即在函数的定义中使用函数自身的计算方法。递归算法可以用来解决许多计算问题,例如搜索、排序和递推。递归算法通常包括一个基本情况(即不再使用递归的情况)和一个递归情况,在递归情况中,函数调用自身来解决更小的问题。
一、含义不同:
递归是重复调用函数自身实现循环。迭代是函数内某段代码实现循环,循环代码中参与运算的变量同时是保存结果的变量,当前保存的结果作为下一次循环计算的初始值。
递归循环中,遇到满足终止条件的情况时逐层返回来结束。迭代则使用计数器结束循环。当然很多情况都是多种循环混合采用,这要根据具体需求。
二、结构不同:
递归与迭代都是基于控制结构:迭代用重复结构,而递归用选择结构。 递归与迭代都涉及重复:迭代显式使用重复结构,而递归通过重复函数调用实现重复。
递归与迭代都涉及终止测试:迭代在循环条件失败时终止,递归在遇到基本情况时终止,使用计数器控制重复的迭代和递归都逐渐到达终止点:迭代一直修改计数器,直到计数器值使循环条件失败;递归不断产生最初问题的简化副本,直到达到基本情况。
递归算法一般用于解决三类问题:
(1)数据的定义是按递归定义的。(Fibonacci函数)
(2)问题解法按递归算法实现。
这类问题虽则本身没有明显的递归结构,但用递归求解比迭代求解更简单,如Hanoi问题。
(3)数据的结构形式是按递归定义的。
如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归地描述。
以上内容参考:百度百科-递归
07《算法入门教程》递归算法
本节内容是递归算法系列之一:递归的介绍,主要介绍了递归的定义,选择了数学归纳法这一数学模型帮助大家可以更好的理解递归的概念,然后明确了一个递归算法必须要具备的三要素,最后说明了一下哪些问题适合应用递归算法求解分析。
递归(Recursion),是计算机科学与技术领域中一种常见的算法思想。
在数学和计算机领域中,递归主要是指在函数的定义中使用函数自身的方法。顾名思义,递归主要包含两个意思, 递 和 归 ,这个是递归思想的精华所在。递归就是有去(递去)有回(归来)。“有去” 是指递归问题可以分解成若干个规模较小、与原问题形式相同的子问题,这些子问题可以和原问题用相同的方法来求解。“有回” 是指这些问题的演化过程是一个从大到小,并且最终会有一个明确的终点,一旦达到终点,就可以从终点原路返回,解决原问题。
很多时候,大家都在思考递归在数学上面应该如何表示了,毕竟对于数学的简单理解比起我们直接写代码起来还是要简单很多的。观察递归,我们会很容易发现递归的数学模型类似于 数学归纳法 ,这个在高中的数列里面就已经开始应用了。数学归纳法常见的描述如下
数学归纳法适用于将需要解决的原问题转换为解决他的子问题,而其中的子问题又可以变成子问题的子问题,而且这些问题都是同一个模型,可以用相同的处理逻辑归纳处理。当然有一个是例外的,就是归纳结束的那一个处理方法不能适用于其他的归纳处理项。递归同样的是将大的问题分解成小问题处理,然后会有一个递归的终止条件,满足终止条件之后开始回归。
数学里面有一个很有名的斐波那契数列,我们在编程求解斐波那契数列的时候就会用到递归的思想,在后续的内部中会具体讲到。
在明确递归的定义及数学模型之后,我们需要掌握递归的三要素:
按照之前的说明,递归应该是有去有回的,这样递归就必须有一个明确的分界点,递归可以在什么时候结束。程序一旦达到这个临界点,就不用继续递归重复下去了。简单来说,递归的终止条件就是为了防止出现无限递归的情况。
如前面说到递归需要一个终止条件一样,在达到递归的终止条件时,需要有一个对应终止条件的程序处理方法。一般而言,在达到递归的终止条件时,对应的问题都是很容易解决的,可以快速的给出问题的解决方案。
递归的本质上还是要将一个大的问题分解成各个逻辑相同的小问题,所以递归过程中一个重要的步骤就是提取递归中重复的逻辑规则,以便利用相同的处理方式进行处理。
按照以上递归的三要素,递归程序的一般处理可以总结成下面的伪代码:
在日常的生活学习中,递归算法一般可以用来解决很多实际问题。回顾一下我们之前学习的排序算法,其中快速排序利用了递归的思想进行解决。总而言之,递归在很多场景中都有应用。
比如说一个常见的对于操作系统里面删除指定路径下的文件夹里内容以及子文件夹里面内容的操作,就可以利用递归思想完成。这个时候递归的终止条件就是判断当前路径是文件,就可以直接删除;发现当前路径是文件夹,则递归调用方法,进入文件夹内部删除里面的文件内容。
总而言之,递归问题在现实学习科研中经常会遇到,这是一种解决问题的思路与方法,将大问题拆分成小问题,然后求解小问题之后回归归纳,得出整个问题的求解结果。
本节主要介绍了递归的定义及基本概念,在学完本节课程之后,需要明白递归的基础逻辑是什么样的,如何自己去设计一个递归算法,在设计一个递归算法时需要考虑到哪些问题,以及我们日常中常见的递归问题。
递归是什么?要详细解释
阶乘, 斐波那契数列, 快速排序, 还有汉诺塔问题, 都是递归的比较经典的问题, 你要什么例子呢? 你究竟是想学递归还是做什么? 楼上几位讲得是不错的, 唯一遗憾的是都不是用PASCAL语言编的.
下面试一下用PASCAL编一个汉诺塔的程序, 我手头没有书, 想到哪编到哪, 不一定太规范.
有A, B, C三个柱, 在A上N个盘子, 要移到C上去.
用中文建一个程序就是:
begin
移(N-1)个盘子(A到B, 以C为中介); {顶上的盘子}
移1个盘子(A到C); {最底的盘子}
移(N-1)个盘子(B到C, 以A为中介); {第一步移到B的盘子}
end.
对于移一个盘子, 我们只要简单地打印一下就可:
procedure MoveSingle(Origin, Dest: Char);
begin
Writeln(Origin, '==>', Dest);
end;
这一段不编子程序也可.
对于移动多个盘子, 按前面分析的, 可如此实现:
procedure MoveMult(Origin, Dest, Medi: Char, n: Integer);
begin
MoveMult(Origin, Medi, Dest, n-1); {将顶上的盘子移走}
MoveSingle(Origin, Dest); {移最下的盘子}
MoveMult(Medi, Dest, Origin, n-1); {再移顶上的盘子}
end;
注意, 在MoveMult子程序中又调用了MoveMult自身, 这就是所谓的递归.
分析一下, 当有3个盘子时, 为: 先移2个(A==>B), 再移底部的(A==>C), 再把B上的2个移至C.
那么移2个是如何实现的呢? 先移1个(Ori==>Med), 再移1个(Ori==>Dest), 再移一个(Med==>Dest).
移1个时算法如何? 显然又要调用移0个, 而移0个则调用移-1个, 这显然有问题了. 程序一直会进行下去, 直到堆栈溢出为止, 程序死了.
解决的办法是: 当个数为1时直接调用MoveSingle不再递归.
所以递归要有一个终止条件, 否则会无限进行下去. 修改后的递归算法为:
procedure MoveMult(Origin, Dest, Medi: Char, n: Integer);
begin
if n > 1 then {当盘子数大于1时递归}
begin
MoveMult(Origin, Medi, Dest, n-1); {将顶上的盘子移走}
MoveSingle(Origin, Dest); {移最下的盘子}
MoveMult(Medi, Dest, Origin, n-1); {再移顶上的盘子}
end else MoveSingle(Origin, Dest); {当盘子数不大于1时直接移动}
end;
无限递归是递归算法中要注意的, 如果你设计多了, 自然知道什么时候可能会出现无限递归.
完整程序为:
program Hanoi(input, output);
var
n: Integer;
procedure MoveSingle(Origin, Dest: Char);
begin
Writeln(Origin, '==>', Dest);
end;
procedure MoveMult(Origin, Dest, Medi: Char, n: Integer);
begin
if n > 1 then
begin
MoveMult(Origin, Medi, Dest, n-1);
MoveSingle(Origin, Dest);
MoveMult(Medi, Dest, Origin, n-1);
end else MoveSingle(Origin, Dest);
end;
begin
Writeln('Hanoi program');
Write('Input a number: ');
Readln(n);
MoveMult('A', 'C', 'B', n);
end.
没经调试, 如果你要用的话, 自己测试一下.
递归通俗的讲就是一个函数在其代码中反复调用自身。你应该知道菲波纳契数列,这个数列的定义是
f(x)=1 (x=1)
f(x)=2 (x=2)
f(x)=f(x-1)+f(x-2) (x>2)
也就是说从第三项开始的每一项的值都等于是前两项之和。这在数学中叫递推数列--高中数学内容。
如果把它变为一个要求第n个菲波纳契数的代码的话,应该如下所示(为了避免语言不通:)我使用伪代码):
int f(int step)
在这里x为上面所说的x变量,也就是要求的是第x项的值
{
if step=1
{
return 1
}
else if step=2
{
return 2
}
如果求得是第一项和第二项的话,就分别返回1和2,并退出函数
return f(x-1)+f(x-2)
否则的话就返回前面两项的和
}
这里的关键是最后一句。这里函数的返回直又要反过去调用它自身计算前面两项的值,这样就会反复调用,直到x变量在某次调用中变为1和2,返回已知的第一项和第二项的值,在层层返回,最后得出要求的第x项的值
说到本质的话,递归是一段程序的代码反复效用,把程序的参数等变量保存在一个堆栈里,直到到了边界条件以后再层层返回,将堆栈中的数据弹出计算,最后得到结果
递归是一种重要的编程技术。该方法用于让一个函数从其内部调用其自身。一个示例就是计算阶乘。0 的阶乘被特别地定义为 1。 更大数的阶乘是通过计算 1 * 2 * ...来求得的,每次增加 1,直至达到要计算其阶乘的那个数。
下面的段落是用文字定义的计算阶乘的一个函数。
“如果这个数小于零,则拒绝接收。如果不是一个整数,则将其向下舍入为相邻的整数。如果这个数为 0,则其阶乘为 1。如果这个数大于 0,则将其与相邻较小的数的阶乘相乘。”
要计算任何大于 0 的数的阶乘,至少需要计算一个其他数的阶乘。用来实现这个功能的函数就是已经位于其中的函数;该函数在执行当前的这个数之前,必须调用它本身来计算相邻的较小数的阶乘。这就是一个递归示例。
递归和迭代(循环)是密切相关的 — 能用递归处理的算法也都可以采用迭代,反之亦然。确定的算法通常可以用几种方法实现,您只需选择最自然贴切的方法,或者您觉得用起来最轻松的一种即可。
显然,这样有可能会出现问题。可以很容易地创建一个递归函数,但该函数不能得到一个确定的结果,并且不能达到一个终点。这样的递归将导致计算机执行一个“无限”循环。下面就是一个示例:在计算阶乘的文字描述中遗漏了第一条规则(对负数的处理) ,并试图计算任何负数的阶乘。这将导致失败,因为按顺序计算 -24 的阶乘时,首先不得不计算 -25 的阶乘;然而这样又不得不计算 -26 的阶乘;如此继续。很明显,这样永远也不会到达一个终止点。
因此在设计递归函数时应特别仔细。如果怀疑其中存在着无限递归的可能,则可以让该函数记录它调用自身的次数。如果该函数调用自身的次数太多,即使您已决定了它应调用多少次,就自动退出。
下面仍然是阶乘函数,这次是用 JScript 代码编写的。
// 计算阶乘的函数。如果传递了
// 无效的数值(例如小于零),
// 将返回 -1,表明发生了错误。若数值有效,
// 把数值转换为最相近的整数,并
// 返回阶乘。
function factorial(aNumber) {
aNumber = Math.floor(aNumber); // 如果这个数不是一个整数,则向下舍入。
if (aNumber < 0) { // 如果这个数小于 0,拒绝接收。
return -1;
}
if (aNumber == 0) { // 如果为 0,则其阶乘为 1。
return 1;
}
else return (aNumber * factorial(aNumber - 1)); // 否则,递归直至完成。
关于递归算法
你输入了三次,所以递归有三层,最外面一层是 a = A,程序停止在if(a!= '#') printf();
中间的一层是 a = B,程序同样停止在if(a!= '#') printf(); 最里面的一层,也就是你输入a = #,
程序在判断完两个if后返回到上一层,if(a! ='#') printf("%c\n",a); 输出 B ,然后再返回上一层输出 A
递归算法怎么理解
问题一:递归算法还不是很理解!!高手教一教! 递归(recursion)是指把一个大的问题转化为同样形式但小一些的问题加以解决的方法。C语言允许一个函数调用它本身,这就是递归调用。即在调用一个函数的过程中又直接或间接地调用函数本身。不加控制的递归都是无终止的自身调用,程序中是绝对不应该出现这种情况的。为了防止无休止的递归,程序中应控制递归的次数,在某条件成立时进行递归,条件不成立不进行递归调用。并且在递归的调用过程中,不断改变递归的条件,以使递归条件不再成立。
同一问题可能既可以用递归算法解决,也可以用非递归算法解决,递归往往算法设计简单,出奇制胜,而普通算法(通常用循环解决)往往设计稍复杂。但执行效率递归算法逊于循环算法。递归反复调用自己,需要占用较多内存和计算机时间。但有一些问题只有用递归方法才能解决,如著名的汉诺塔问题。
递归程序设计的关键就是考虑问题的两种情况,一种是普遍情况即函数值等于把问题递推一步后的本函数的调用,一种是极端或端点情况,此时函数值有确定的一个值而无须再调用本函数。递归的过程就是从普遍情况逐步过渡到端点情况的过程。
例子:
5个坐在一起论年龄,问第五个人多少岁?他说比第四个人大两岁。问第四个人多少岁,他说比第三个人大两岁。问第三个人多少岁,他说比第二个人大两岁。问第二个人多少岁,他说比第一个人大两岁。问第一个人多少岁,他说10岁。请问第五个人几岁?
int age(int n)
{ int x;
if(n>1) x=age(n-1)+2;
else if(n==1) x=10;
return x;
}
void main( )
{ printf(%d,age(5));}
问题二:什么是递归算法 递归算法就是一个函数通过不断对自己的调用而求得最终结果的一种思维巧妙但是开销很大的算法。
比如:
汉诺塔的递归算法:
void move(char x,char y){
printf(%c-->%c\n,x,y);
}
void hanoi(int n,char one,char two,char three){
/*将n个盘从one座借助two座,移到three座*/
if(n==1) move(one,three);
else{
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
}
}
main(){
int n;
printf(input the number of diskes:);
scanf(%d,&n);
printf(The step to moving %3d diskes:\n,n);
hanoi(n,'A','B','C');
}
我说下递归的理解方法
首先:对于递归这一类函数,你不要纠结于他是干什么的,只要知道他的一个模糊功能是什么就行,等于把他想象成一个能实现某项功能的黑盒子,而不去管它的内部操作先,好,我们来看下汉诺塔是怎么样解决的
首先按我上面说的把递归函数想象成某个功能的黑盒子,void hanoi(int n,char one,char two,char three); 这个递归函数的功能是:能将n个由小到大放置的小长方形从one 位置,经过two位置 移动到three位置。那么你的主程序要解决的问题是要将m个的汉诺块由A借助B移动到C,根据我们上面说的汉诺塔的功能,我相信傻子也知道在主函数中写道:hanoi(m,A,B,C)就能实现将m个块由A借助B码放到C,对吧?所以,mian函数里面有hanoi(m,'A','C','B');这个调用。
接下来我们看看要实现hannoi的这个功能,hannoi函数应该干些什么?
在hannoi函数里有这么三行
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
同样以黑盒子的思想看待他,要想把n个块由A经过B搬到C去,是不是可以分为上面三步呢?
这三部是:第一步将除了最后最长的那一块以外的n-1块由one位置经由three搬到two 也就是从A由C搬到B 然后把最下面最长那一块用move函数把他从A直接搬到C 完事后 第三步再次将刚刚的n-1块借助hanno处函数的功能从B由A搬回到C 这样的三步实习了n块由A经过B到C这样一个功能,同样你不用纠结于hanoi函数到底如何实现这个功能的,只要知道他有这么一个神奇的功能就行
最后:递归都有收尾的时候对吧,收尾就是当只有一块的时候汉诺塔怎么个玩法呢?很简单吧,直接把那一块有Amove到C我们就完成了,所以hanoni这个函数最后还要加上 if(n==1)move(one,three);(当只有一块时,直接有Amove到C位置就行)这么一个条件就能实现hanoin函数n>=1时......>>
问题三:怎么更好地终极理解递归算法 递归的基本思想是把规模大的问题转化为规模小的相似的子问题来解决。在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况。另外这个解决问题的函数必须有明显的结束条件,这样就不会产生无限递归的情况了。
需注意的是,规模大转化为规模小是核心思想,但递归并非是只做这步转化,而是把规模大的问题分解为规模小的子问题和可以在子问题解决的基础上剩余的可以自行解决的部分。而后者就是归的精髓所在,是在实际解决问题的过程。
问题四:怎样才能深刻理解递归和回溯? 递归的精华就在于大问题的分解,要学会宏观的去看问题,如果这个大问题可分解为若干个性质相同的规模更小的问题,那么我们只要不断地去做分解,当这些小问题分解到我们能够轻易解决的时候,大问题也就能迎刃而解了。如果你能独立写完递归创建二叉树,前序、中序、后序递归遍历以及递归计算二叉树的最大深度,递归就基本能掌握了。
回溯本人用得很少,仅限于八皇后问题,所以帮不上啥了。
问题五:二叉树的递归算法到底该怎么理解 这不就是在二叉排序树上的递归查找,看程序
tree& find(const T& d, tree& t){
if(t==NULL) return t;如果二叉树为空则返回空,查找失败
if(t->data==d) return t;否则,如果当前根结点关键码为d,则查找成功,当前根结点为待查找结点
if(d>t->data) return find(d, t->right);如果比根的关键码大就递归查找右子树
return find(d, t->left);如果比根的关键码小就递归查找左子树
}
二叉树的递归定义的含义就是非空二叉树,除了根以外,左右子树都是二叉树(可以为空)
问题六:怎么理解递归算法?我看了代码但还是不理解? 函数自己调用自己就是递归啊。
从前有座山,山里有座庙,庙里有个老和尚给小和尚讲故事。讲的内容是:
从前有座山,山里有座庙,庙里有个老和尚给小和尚讲故事,讲
从前有座山,山里有座庙,庙里有个老和尚给小和尚讲故事……
跟循环差不多。而且浪费栈空间,效率不高。能够转化为循环最好。
问题七:数据结构中的二叉树中的递归怎么理解? 以中序遍历为例,思想是:
若二叉树为空,则空操作;否则
(1)中序遍历左子树
(中序遍历左子树时也是这三步)
(2)访问根结点
(3)中序遍历右子树
(当然右子树也是重复着三步)
示例代码:
int InOrderTraverse(BiTree T)
{
if(T)
{
InOrderTraverse(T->lchild);
printf(%d\t,T->data);
InOrderTraverse(T->rchild);
}
return OK;
}
问题八:java递归算法,怎么理解??? n! = (n-1)*n!
简单理解,就是目前的所有任务,等于前面所有的任务+现在的任务。
比如你求 1。。。100的加法总和
实际上是 1... 99 的加法总和 + 100 就是了。
这就是递归的来源。
你只需要计算你前一步的任务,然后加上自己,就OK了。
前一步,在再次调用前前一步......
问题九:新手一个,有什么更好理解递归的方法吗?(c++) 递归的话就是重复调用方法直到满足条件为止就停止这个方法,就跟循环类似,不过循环使用的方法一边比较简单
问题十:递归的原理解释 递归的底层实现其实是一个栈.栈的特点是后进先出,也就是最后进入栈的事件是最先被处理的.
递归就是这样运作.比如计算阶乘函数F(n)=n!=n*F(n-1)=....
写成递归,我用java
public static long F(long num){
if(num