递归c语言,c语言递归的问题
递归c语言,c语言递归的问题详细介绍
本文目录一览: C语言中的递归是什么意思
要理解递归,首先你要理解递归
简单来说就是一个函数调用到了自己,就可以称为递归.下面是简单的求n!的例子:
#include
#include
int fac(int n)
{
if(n==0)return 1;
return n*fac(n-1);
}
void main()
{
printf("%d\n",fac(6));
}
在函数调用中,如果直接或间接地调用该函数本身,称为递归调用.递归调用有时也称为循环定义.
例子:计算 n! (可表示为: n!=n(n-1)!)
#include
main()
{
long int fac(int n); /*函数声明*/
long int s;
int i;
scanf("%d",&i);
s=fac(i);
printf("%2d!=%1d\n",i,s);
}
long int fac(int n)
{
long int fa;
if(n==0)
fa=1;
else
fa=n*fac(n-1); / *采用了递归算法*/
return fa;
}
也就是一个函数的中再调用该函数,也就是说是循环的递归调用,但必须得有一个判断结束的条件,否则都成了死循环!
程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
扩展资料:
递归的应用
1、数据的定义是按递归定义的。(Fibonacci函数)
2、问题解法按递归算法实现。这类问题虽则本身没有明显的递归结构,但用递归求解比迭代求解更简单,如Hanoi问题。
3、数据的结构形式是按递归定义的。
递归的缺点
递归算法解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。
参考资料来源:百度百科-递归
c语言递归函数
递归求
阶乘
的吧,不过你写的有问题,函数既然接受
形参
n,在函数里就不用再读取了;而且函数返回的是long类型,应该
强制转换
返回值
。
这样吧,你不要管什么递归,你自己想一下,不用递归,怎么解这个问题,最后得出的思路肯定就恰好是递归的过程
这个是要用图来说明的…一画图什么都明白了
对于递归,我打个比方吧!
就像一根缠绕着的铁链,知道从第一个环就能解开,但是现在只能拿到最后一个环,所以就必须从最后一个环顺着链条往头找,直到找到第一个,就相当于找到递归的跳出条件了
例子不是很恰当
不明白的话,留言,一定给你讲清楚…留言比回
这是道汉诺塔的题目
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
意思是说
1)如果我把上面的 n-1个元素放到第二个柱子上
2)那么我就可以把最下面的棋子放到第三个柱子上
3)然后我再把第二个柱子上的n-1个棋放到第三个柱子上
第二个参数是源地址,第四个参数是目标地址,第三个参数是暂存地址。
分成三组:
(一),
目的:将1号和2号从A移到B
调用函数:hanoi(2,'A', 'C', 'B')。
在hanoi(2,'A', 'C', 'B')中递归调用如下:
A-->C----hanoi(1,'A', 'B', 'C')
A-->B----hanoi(1,'A', 'C', 'B')
C-->B----hanoi(1,'C', 'A', 'B')
(二),
目的:将3号从A移到C
调用函数:hanoi(1,'A', 'B', 'C')
A-->C
(三),
目的:将1号和2号从B移到C
调用函数:hanoi(2,'B', 'A', 'C')
在hanoi(2,'B', 'A', 'C')中递归递归如下:
B-->A----hanoi(1,'B', 'C', 'A')
B-->C----hanoi(1,'B', 'A', 'C')
A-->C----hanoi(1,'A', 'B', 'C')
=====================
总共调用了7次函数,
只要hanoi()的第一个参数大于1,它就会在内部调用自身3次,“直到第一个参数=1,然后调用printf()”。
hanoi(n, ...)调用hanoi(1, ...)的次数为2的n次方减去一。
递归函数:
编程语言中,函数Func(Type a,……)直接或间接调用函数本身,则该函数称为递归函数。递归函数不能定义为内联函数。
在数学上,关于递归函数的定义如下:对于某一函数f(x),其定义域是集合A,那么若对于A集合中的某一个值X0,其函数值f(x0)由f(f(x0))决定,那么就称f(x)为递归函数。
函数介绍:
在数理逻辑和计算机科学中,递归函数或μ-递归函数是一类从自然数到自然数的函数,它是在某种直觉意义上是"可计算的" 。事实上,在可计算性理论中证明了递归函数精确的是图灵机的可计算函数。递归函数有关于原始递归函数,并且它们的归纳定义(见下)建造在原始递归函数之上。但是,不是所有递归函数都是原始递归函数 — 最著名的这种函数是阿克曼函数。
其他等价的函数类是λ-递归函数和马尔可夫算法可计算的函数。
例子:
//代码1
void func()
{
//...
if(...)
func();
else
//...
}
条件:
一个含直接或间接调用本函数语句的函数被称之为递归函数,在上面的例子中能够看出,它必须满足以下两个条件:
1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;
2) 必须有一个终止处理或计算的准则。
梵塔的递归函数:
//C
void hanoi(int n,char x,char y,char z)
{
if(n==1)
move(x,1,z);
else
{
hanoi(n-1,x,z,y);
move(x,n,z);
hanoi(n-1,y,x,z);
}
}
C语言什么是递归方法?
你把你的函数拆开看,比如,你求5的阶乘,那么你把那个函数,看成多个,
你复制出来
func_1至func_n;然后调用的时候
第i个函数,调用第i+1个函数.这相可以实现同样的功能.
其实递归就相当于这多个函数,只是调用的时候,都是调用它自己,这个时候,就把函数本身看成一个新的函数.直到函数返回.
简单来说就是一个函数调用到了自己,就可以称为递归.下面是简单的求n!的例子:
#include
#include
int fac(int n)
{
if(n==0)return 1;
return n*fac(n-1);
}
void main()
{
printf("%d\n",fac(6));
}
C语言关于函数的递归
你的递归程序是错的,我转来个对的,带讲解的,你看看。
语言函数的递归和调用
一、基本内容:
C语言中的函数可以递归调用,即:可以直接(简单递归)或间接(间接递归)地自己调自己。
要点:
1、C语言函数可以递归调用。
2、可以通过直接或间接两种方式调用。目前只讨论直接递归调用。
二、递归条件
采用递归方法来解决问题,必须符合以下三个条件:
1、可以把要解决的问题转化为一个新问题,而这个新的问题的解决方法仍与原来的解决方法相同,只是所处理的对象有规律地递增或递减。
说明:解决问题的方法相同,调用函数的参数每次不同(有规律的递增或递减),如果没有规律也就不能适用递归调用。
2、可以应用这个转化过程使问题得到解决。
说明:使用其他的办法比较麻烦或很难解决,而使用递归的方法可以很好地解决问题。
3、必定要有一个明确的结束递归的条件。
说明:一定要能够在适当的地方结束递归调用。不然可能导致系统崩溃。
三、递归实例
例:使用递归的方法求n!
当n>1时,求n!的问题可以转化为n*(n-1)!的新问题。
比如n=5:
第一部分:5*4*3*2*1
n*(n-1)!
第二部分:4*3*2*1
(n-1)*(n-2)!
第三部分:3*2*1
(n-2)(n-3)!
第四部分:2*1
(n-3)(n-4)!
第五部分:1
(n-5)!
5-5=0,得到值1,结束递归。
源程序:
fac(int
n)
{int
t;
if(n==1)||(n==0)
return
1;
else
{
t=n*fac(n-1);
return
t;
}
}
main(
)
{int
m,y;
printf(“Enter
m:”);
scanf(“%d”,&m);
if(m<0)
printf(“Input
data
Error!\n”);
else
{y=fac(m);
printf(“\n%d!
=%d
\n”,m,y);
}
}
四、递归说明
1、当函数自己调用自己时,系统将自动把函数中当前的变量和形参暂时保留起来,在新一轮的调用过程中,系统为新调用的函数所用到的变量和形参开辟另外的存储单元(内存空间)。每次调用函数所使用的变量在不同的内存空间。
2、递归调用的层次越多,同名变量的占用的存储单元也就越多。一定要记住,每次函数的调用,系统都会为该函数的变量开辟新的内存空间。
3、当本次调用的函数运行结束时,系统将释放本次调用时所占用的内存空间。程序的流程返回到上一层的调用点,同时取得当初进入该层时,函数中的变量和形参所占用的内存空间的数据。
4、所有递归问题都可以用非递归的方法来解决,但对于一些比较复杂的递归问题用非递归的方法往往使程序变得十分复杂难以读懂,而函数的递归调用在解决这类问题时能使程序简洁明了有较好的可读性;但由于递归调用过程中,系统要为每一层调用中的变量开辟内存空间、要记住每一层调用后的返回点、要增加许多额外的开销,因此函数的递归调用通常会降低程序的运行效率。
五、程序流程
fac(int
n)
/*每次调用使用不同的参数*/
{
int
t;
/*每次调用都会为变量t开辟不同的内存空间*/
if(n==1)||(n==0)
/*当满足这些条件返回1
*/
return
1;
else
{
t=n*fac(n-1);
/*每次程序运行到此处就会用n-1作为参数再调用一次本函数,此处是调用点*/
return
t;
/*只有在上一句调用的所有过程全部结束时才运行到此处。*/
}
}
c语言递归函数的问题?
通过分析这个代码,建立了如图的树。
1、当进去A时,num = 1;
2、接着往左进去B,num = 2;
3、往B左边及右边因为是NULL直接返回2处,再返回到1处;
4、接着往A右边C,此时num=3,这里把返回值C压入寄存器RAX,代码返回到A,但是最上层A处没有接收返回值,此时A退出,main函数从RAX取出返回值赋值给变量a。
这就是整个调用过程,这里返回值并不是最上层的返回值,是C的返回值,之所以能得到这个值是这个程序没有同步其它地方使用了RAX寄存器,它的值没有被修改。
通过分析这个代码,建立了如图的树。
1、当进去A时,num = 1;
2、接着往左进去B,num = 2;
3、往B左边及右边因为是NULL直接返回2处,再返回到1处;
4、接着往A右边C,此时num=3,这里把返回值C压入寄存器RAX,代码返回到A,但是最上层A处没有接收返回值,此时A退出,main函数从RAX取出返回值赋值给变量a。
这就是整个调用过程,这里返回值并不是最上层的返回值,是C的返回值,之所以能得到这个值是这个程序没有同步其它地方使用了RAX寄存器,它的值没有被修改。
用C语言的函数递归方法来求
#include
#include
void fun2(int m) {
for (int i = 2; i <= m / 2; i++) {
if (m % i == 0)
printf("%d ",i);
}
}
void fun1(int m) {
int i;
for (i = 2; i * i <= m; i++)
if (m % i == 0)
break;
if (i * i > m)
printf("%d is a prime number", m);
else
fun2(m);
}
int main() {
int n;
scanf("%d", &n);
fun1(n);
return 0;
}
#include
#include
void fun2(int m)
{
int k=0,a[10];
for(int i=2;i
<m;i++)
if(m%i==0)
a[k++]=i;
for(int i=0;i
<k;i++)
{
printf("%d",a[i]);
if(i!=k-1)
printf(",");
}
}
void fun1(int m)
{
if(m<2)
printf("%d is a prime number",m);
for(int i=2;i*i<=m;i++)
if(m%i==0)
fun2(m);
else
printf("%d is a prime number",m);
}
int main( )
{ int n;
scanf("%d",&n);
fun1(n);
return 0;
}
</k;i++)
</m;i++)
c语言递归问题
首先我们回答一下,你的这个题目中是有用到递归的。
我们先来了解下什么是递归:
递归的定义:直接或间接调用自己的函数成为递归函数(recursionfunction)。在求解某些具有随意性的复杂问题时经常使用递归,例如求解阶乘或者两个数的最大公约数等。因为这时解的具体“大小”不受限制,函数可以一直递归调用,直到问题解决。
递归的要求:递归函数必须定义一个终止条件;否则,函数就会“永远”递归下去,这意味着函数会一直调用自身直到程序栈耗尽,这种“永远”递归下去的现象叫做“无限递归错误”(infiniterecursion error)。
递归的特点:
1、在函数f()中,会对函数f()自己进行调用。
2、无限递归实际上是不允许的;递归函数必须定义一个终止条件,即什么情况下终止递归,终止继续调用自己,如果没有终止条件,那么函数将一直调用自己,知道程序栈耗尽,这时候等于是写了一个Bug!
3、 递归算法解题通常代码比较简洁,但不是很容易读懂。
4、 递归的调用需要建立大量的函数的副本,尤其是函数的参数,每一层递归调用时参数都是单独的占据内存空间,他们的地址是不同的,因此递归会消耗大量的时间和内存。而非递归函数虽然效率高,但相对比较难编程。
5、 递归函数分为调用和回退阶段,递归的回退顺序是它调用顺序的逆序。
如果以上对你有帮助,青采纳一下, 谢谢。
c语言递归的问题
按箭头来执行,其实内部用的是堆栈的知识。其实最关键的是何时才结束递归,对于此问题n<=0 时执行ans = 1返回;
long fact (int n) //使用递归算法计算阶乘,也就是定义这样一个函数,接下来在大括号里来写这样一个long fact函数的功能
{
long ans;//定义一个长整型的ans
if (n>0)
ans = n*fact(n-1);//如果n大于0,执行ans = n*fact(n-1),并且一次一次执行下去。
else
ans = 1;如果n不大于0,就执行ans = 1
return 0;//最后返回0
}
这个代码有错误,最后返回应该是return ans;而不应该是return 0;。
以6!为例:
ans=(6乘
(fact(5)乘
(fact(4)乘
(fact(3)乘
(fact(2)乘
(fact(1)乘
(fact(0)=1)))))))
最后由return ans;返回6x5x4x3x2x1x1=720。
好象应该返回return ans;
递归就是调用自己的意思,而且你写错了,应该是return ans;返回值是自己,而不是0;比如说,实参传递形参给它n=2;
你如果觉得调用自己不明白的话,你就把上面的函数定义成:
fact1,fact2,fact3他们只是名字不一样,自定义函数的内容都是完全相同的。
然后自定义函数fact1开始运行:
n>0;成立,执行ans=n*fact2(n-1); //相当于ans=2*fact2(n-1);
ans这句语句调用fact2自定义函数,实参n-1=1传给fact2的形参。
n>0;成立,执行ans=*fact3(n-1); //这是n=1,形参收到的数据是1,1*fact3(n-1)
实参n-1=0传给fact3的形参;
n>0不成立,直接ans=1。
之前都是调用的过程,下面是返回值
先是从fact3返回1,返回到fact2,
fact2中ans=1*1=1,这个值返回到fact1;
fact1中ans=2*1=2,这个值返回到主函数。
同理,如果n=5的话,相当于要写fact1,fact2……fact6.这6个函数。
返回的结果是1*1*2*3*4*5=120到主函数。
但是如果你把这六个函数都写出来,要浪费多少时间,既然他们的内容都是一样的,为什么不把名字定为1个,然后自己调用自己,这就形成了递归函数了。
递归函数相当于调用多次自定义函数,而每次调用的对象都是同一个,只是每次传递的参数发生了变化。
希望你多看几遍,不明白继续问,纯手写,望采纳。
C语言什么是递归
递归方法的概念
类方法成员间允许相互调用,也可以自己调用自己。类的方法如果在方法体内直接或间接地自己调用自己就称为递归方法。
递归基本思想就是“自己调用自己”。递归方法实际上体现了“依此类推”、“用同样的步骤重复”这样的思想,它可以用简单的程序来解决某些复杂的计算问题。
递归调用在完成阶乘运算、级数运算、幂指数运算等方面特别有效。
在执行递归操作时,C#语言把递归过程中的信息保存在堆栈中。如果无限循环地递归,或者递归次数太多,则产生“堆栈溢出”错误
例:用递归方法求阶乘。利用的数学公式为n!=n*(n-1)!。当n=0时,n!=1。
代码如下:
public long F(int n)
{
if (n==1)
return 1;
else
return n*F(n-1);
}
C语言递归问题!
递归算法:是一种直接或者间接地调用自身的算法。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归算法的特点
递归过程一般通过函数或子过程来实现。
递归算法:在函数或子过程的内部,直接或者间接地调用自己的算法。
递归算法的实质:是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
递归算法所体现的“重复”一般有三个要求:
一是每次调用在规模上都有所缩小(通常是减半);
二是相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
三是在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。 例子如下:
描述:把一个整数按n(2<=n<=20)进制表示出来,并保存在给定字符串中。比如121用二进制表示得到结果为:“1111001”。
参数说明:s: 保存转换后得到的结果。
n: 待转换的整数。
b: n进制(2<=n<=20)
void
numbconv(char *s, int n, int b)
{
int len;
if(n == 0) {
strcpy(s, "");
return;
}
/* figure out first n-1 digits */
numbconv(s, n/b, b);
/* add last digit */
len = strlen(s);
s[len] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n%b];
s[len+1] = '\0';
}
void
main(void)
{
char s[20];
int i, base;
FILE *fin, *fout;
fin = fopen("palsquare.in", "r");
fout = fopen("palsquare.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%d", &base);
/*PLS set START and END*/
for(i=START; i <= END; i++) {
numbconv(s, i*i, base);
fprintf(fout, "%s\n", s);
}
exit(0);
}