C语言:递归(新手入门)

前言

再写这篇文章之前,其实我已经写过一篇有关递归的文章了,但考虑到那篇文章是有关二叉树的,对于刚入门的朋友来说,是有难度的。所以,才有这篇有关递归入门的文章。(有兴趣的朋友可以去看看:二叉树深度优先探索相关题目

递归简介

在C语言中,函数是允许调用自己的,这种调用过程称之为递归。而递归,顾名思义就是在传递函数的调用和归还函数的结果。递归有大事化小的能力,写起代码来很容易,而理解起来却很抽象。
在这里插入图片描述
由图片知道,递归是需要条件来结束递归的,否则将会无限递归下去。
一般来说,可以使用循环的地方通常都可以使用递归。

递归使用三板斧

1.确定是否能用递归

当某个特性可以被重复或者有规律性执行,一般来说都可以使用递归。

2.确定终止条件

在使用递归函数时,要想好什么时候要停下来,找好终止所需条件。

3.找出递归关系式

使用递归时,我们要想好需要传递什么,返回什么,写好关系式。当然,要清楚函数所求结果是什么。一般来说,我们可以从简单例子入手

例子

下面将通过两个例子来讲解这三板斧的使用。

1.斐波那契数

这是递归使用一个非常经典的例子,
有这样一个数列:1,1,2,3,5,8,13,21…从第三个数开始,每个数是前两个数之和。求第n个数是多少?

三板斧使用

   由题目知道,第三个数开始,每个数是前两个数之和,这种规律性符合我们
   使用递归;例如我们求第三个数,我们很容易知道是1+1=2,但我们此时
   要想好怎么把这个关系式转换成递归的关系式。第一个1为第一个数,第二个
   为第二个数,那么就将他转换为函数形式即可。这时我们很容易知道,n进入
   函数后是不断递减的,那么终止条件(传递函数的终点)就是第一个数和第二个
   数。

在这里插入图片描述

代码

#include<stdio.h>
 int fib(int n)
 {
    
    
 //递归终止条件
     if(n==1||n==2)
    {
    
    
         return 1;
     }
     //递归关系式
     return fib(n-1)+fib(n-2);
 }
 int main()
 {
    
    
 int n=5;
 int sum=fib(n);
 printf("%d",sum);
 return 0;
 }
  结果为:5

2.计算n的k次方

三板斧使用

通过n多次乘自己,很清楚能使用递归。例如,求2的3次方
在这里插入图片描述
由图知,当次方为1时,就是终止条件;而关系式就是n*后面的数。
在这里插入图片描述

#include<stdio.h>
int power(int n,int k)
{
    
    
    if(k==1)
    {
    
    
        return n;
    }
        return n*power(n,k-1);
}
int main()
{
    
    
	power(2,5);
	return 0;
}
   结果:32

循环和递归

上面我们说过,一般能循环的话都能进行递归。有时用循环解决问题比较好,但有时用递归更好。递归方案更简洁,但效率却没有循环高。
例如,求n的阶乘。
代码如下:

#include<stdio.h>
//递归形式
int Fab(int n)
{
    
    
    if(n==1)
    {
    
    
        return 1;
    }
    return Fab(n-1)*n;
}
//循环迭代形式
int Fab(int n)
{
    
    
    int sum=1;
   for(int i=1;i<n;i++)
    {
    
    
        sum=sum*(i+1);
        
    }
    return sum;
}
int main()
{
    
    
    int n=5;
    int sum=Fab(n);
    printf("%d",sum);
    return 0;
}
结果:120

如果看代码的话,我们看得出递归形式明显简洁很多,但实际上,它在使用的过程中是很复杂的。为什么这么说呢?我们知道,调用函数要在内存中临时开辟一块空间进行存储,结束了函数就会归还这块空间(栈区)。递归函数在使用过程中,总是在函数没有使用完就又进入了下一个函数,函数又得开辟空间,循环往复,内存就占用比较多。而循环只是在一个函数内进行使用,故只开辟了一块空间。
在这里插入图片描述
所以,如果一个函数能使用递归和循环的情况下,优先选择循环

递归函数放置的顺序问题

在使用递归过程中,要清楚先做什么再做什么。递归的函数放想要执行语句前还是后,是非常关键的。
如:想将一个整数打印成一个数一个数且数中间用空格隔开。
例子:将1729打印成 1 7 2 9
代码:

#include<stdio.h>
void printf_lone(int n)
{
    
    
    if(n<10)
    {
    
    
        printf("%d ",n);
        return;
    }
    printf("%d ",n%10);
    printf_lone(n/10);
   
}
int main()
{
    
    
    int n=1729;
    printf_lone(n);
    return 0;
}
结果:9 2 7 1

结果竟然和我们想要的结果相反,这时我们就要考虑一下我们的递归思想有没有错误。通过思考,发现我们是从数的右边到数的左边。当我们先打印时,那肯定是先打印9 了,依次递归,那么结果就呈现相反的了。所以,正确的代码是:

#include<stdio.h>
void printf_lone(int n)
{
    
    
    if(n<10)
    {
    
    
        printf("%d ",n);
        return;
    }
    printf_lone(n/10);
    printf("%d ",n%10);
   
}
int main()
{
    
    
    int n=1729;
    printf_lone(n);
    return 0;
}
结果 :1 7 2 9

所以,我们要清楚递归是从哪到哪的,先执行什么,后执行是什么,才能写出正确的代码。

总结

在这里,就简单介绍了递归的使用方法和一些注意事项,由上面例子清楚,我们的终止条件一般都会放在前头,然后才是递归关系式。如果你想巩固递归思想,可以通过专项练习进行巩固。在C语言后面学习道路上,这个递归思想还是非常重要的,不是循环所能解决的。
好了,今天就先到这里,感谢你的观看。

猜你喜欢

转载自blog.csdn.net/m0_74068921/article/details/130415635