嵌入式学习一阶段——C语言:递归

# 递归

    栈的思想:是先进后出!!

    C语言运行时堆栈支持递归函数的实现。递归函数就是直接或者间接调用自身的函数。在许多教科书把计算阶乘和,斐波拉数列用来当作递归的例子

    我决定这个非常不好。在阶乘的例子中,没有啥优越性,在斐波那契的例子,它的效率非常之低。

    在这个地方,我们举一个比较简单的例子,我拿来说明递归。程序的目的是把一个整数从二进制形式转换为可以打印的字符形式!!

    (把整数转换为可以输出的字符! 输入 4267  ,我们需要依次产生字符‘4’ ‘2’ ‘6’ ‘7’)。

    我们采用规定策略是把这个值反复除以10,并打印各个数。例如:4267%10 的余数是7 ,但是我不能直接打印这个余数。我们需要打印的这个数是字符‘7’

    在ASCII码中,字符‘7’的值是55,所以我们需要在余数上加上48来获取正确的字符。

    while(a)

    {

        printf("%c",(a%10)+'0');

        a /= 10;

        //两句话就完成了,只是说获取的答案是反的,我需要4267  , 你打印的是 7624

    }

    我们把这个函数转换成递归来修正这个问题!!

    #include <stdio.h>

    void int_char_ascii(int value)

    {

        int num = 0;

        num = value/10;

        if(num != 0)

        {

            //int_char_ascii(num);

            func

        }

        printf("%c",value % 10 + '0');

    }

    int main()

    {

        int_char_ascii(4267);

        return 1;

    }

    递归是如何帮助我们以正确的顺序打印这些字符????下面就是这个函数的工作流程

    1、将参数值除以10

    2、如果num的值为非0,调用int_char_ascii()打印当前值的各个数字

    3、接着,打印步骤1中出发运算的余数

    一旦你理解了递归,阅读递归函数的最简单的方法不是去纠结它的执行过程,而是相信递归函数会顺利完成它的任务。

    如果你的每一个步骤都正确无误的化, 同时你的限制条件也设置正确,并且每次调用之和更加的接近限制条件就ok了,

    这样子我们的递归函数才能顺利完成它的任务。

## 追踪递归函数

    为了能理解递归函数的工作原理,你需要追踪递归调用的执行过程,所以让我们来进行这项工作。

    追踪一个递归函数执行过程的关键,就是你要理解函数中所声明的变量是如何存储的。

    当函数被调用的时候,它的变量的空间是常见于运行时堆栈上。

    以前调用的函数的变量仍保留栈堆上的,但是他们会被新的函数的变量所覆盖,因此不能被访问。

    当递归函数调用自身的时候,情况也是这样子的。每进行一次新的调用,都会创建一批变量,

    他们将会”覆盖“函数前一次调用所创建的变量。当我们追踪一个递归函数的执行过程的时候,

    必须把分属于不用次调用的变量区分开来,以避免混淆。

    见追踪递归函数.png

## 问题引入

    我们班有10个同学

        我问第10个同学,你几岁了,他说,他比第9个同学大两岁

        我问第9个同学,你几岁了,他说,他比第8个同学大两岁

        ......

        我问第1个同学,你几岁了,他说,他10岁

    请问,第n个同学几岁了!

    写一个函数来完成这个任务

    1、确定任务目标

        求第n个同学年龄

            age

    2、确定完成任务的输入参数

        age(int n)

    3、确定任务完成后,返回值(返回当前第n个学生的年龄)

        int age(int n )

        {

    }

    4、具体的算法实现

        a、你要确定结束条件是什么?

        int age(int n )

        {

            if(n == 1)

            {

                return 10;

            }

            else

            {

                return age(n-1)+2;    //从第n-1个同学的年龄+2

            }

        }

        int main()

        {

            printf("%d\n",age(10));

        }

### 递归的说法:

    直接或者间接调用函数的本身,这个过程称之为”递归”,自己调用自己

## 在什么情况下使用递归??

    是不是所有的问题都可以使用递归??显然不是

    在解决一个问题的时候,解决思路 化成(分解)与问题本身类似或者相同的问题的时候,就可以考虑递归。

    在上面这个例子中:求第n个学生的年龄的 <------------->求第n-1个同学问题+2 <----------->求第n-2个同学的年龄+2..............

    在解决一个问题的过程中,需要解决与这个问题类似的问题,才会去采用递归

    是不是所有的递归函数,C语言都支持?? 肯定不是,原因是:不能无限递归下去

    C语言能解决的递归问题,需要满足两个条件:

        1、问题的本身是就是一个递归------》递归函数式

        2、递归不能无限递归

    适合那些递归到一定程度时,答案就显而易见的,一定要有退出递归的条件,不能无限递归

    什么时候使用递归??

        在你解决思路过程中,发现“递归问题”,并且自己可以写出这个递归函数式的时候!!

    解决问题时:

        要把一个大问题,分解成多个小问题或者多个步骤

        如果这些小问题 或者 多个步骤 中有一个是和原问题类似的,这种情况下就使用递归

    进一步展开,“用自然语言来描述这个意思”

         “再使用形式化语言来描述这个思路”  ---- 递归函数式

    代码

第一步:按照函数的步骤来写函数

第二部:要确定递归的结束条件

第三步:递归函数式

#include<stdio.h>
/*汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower)。
有三根柱子,在一根柱子上从下往上按照大小顺序摞着n片圆盘。
要把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,任何时候,在小圆盘上都不能放大圆盘,
且在三根柱子之间一次只能移动一个圆盘。
问应该如何操作?
*/
int i=0;
int move(int n,char x,char y)
{
    i++;
    printf("第%d步把%d个圆盘从%c移动到%c\n",i,n,x,y);
}

int hannuo(int n,char a,char c,char b)
{
    if(n==1)
    {
        move(n,a,c);
    }
    else
    {
        hannuo(n-1,a,c,b);
        move(n,a,c);
        hannuo(n-1,b,a,c);
    }

}
int main()
{
    int n;
    printf("请输入一个数n:\n");
    scanf("%d",&n);
    hannuo(n,'A','C','B');
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值