C语言—递归

目录

一  函数递归

1 递归介绍

2 例一 顺序打印 

 2 例二 求字符串长度

二  递归与迭代

1 求n的阶乘(不考虑溢出)

2 求第n个斐波那契数。(不考虑溢出)


一  函数递归

1 递归介绍

一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复 杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可 描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。

递归的主要思考方式在于:把大事化小

递归的两个必要条件

 1 存在限制条件,当满足这个限制条件的时候,递归便不再继续。

 2  每次递归调用之后越来越接近这个限制条件。

#include<stdio.h>
int main()// 这是一个最简单的递归
{
       printf("haha\n");
       main();// 无线循环下去  成为死递归
       return 0;
}

2 例一 顺序打印 

//接受一个整型值(无符号),按照顺序打印它的每一位。 例如: 输入:1234,输出 1 2 3 4
#include<stdio.h>
void print(unsigned int x)
{
       if (x > 9)// 如果不加限制条件 递归会无限开辟栈区空间 栈区空间是有限的  最后会栈溢出
       {
              print(x / 10);
       }
       printf("%d ", x % 10);
}
int main()
{
       // 1234%10 == 4
       // 123%10 == 3;
       // 12%10 == 2;
       // 1 % 10 == 1;
       unsigned int a = 0;
       scanf("%d", &a);
       print(a);
       return 0;
}

分析一下

 

递归 就是递推和回归  蓝色是递推 黄色就是回归

那红色数字 1234 123 12 1 这些数字是如何保存的?

那就考虑函数的调用堆栈或者函数栈帧

 2 例二 求字符串长度

// 求字符串长度
int my_strlen(char* s)
{
       int count = 0;
       while (*s != '\0')
       {
              count++;
              s++;
       }
       return count;
}
int main()
{
       char arr[] = "abc";
       // [a b c \0]
       int len = my_strlen(arr);// 数组名是首元素的地址 第一个元素的地址
       printf("%d\n", len);
       return 0;
}
//编写函数不允许创建临时变量,求字符串的长度。不允许创建count
//递归
#include<stdio.h>
#include<string.h>
int my_strlen(char* s)
{
       if (*s == '\0')// *s 拿到的是初始地址 也就是第一个地址 a 的地址
              return 0;
       else
              return 1 + my_strlen(s + 1);//  s + 1 就是地址(指针)往后偏移 拿后面的地址 s指向a  s+1就指向 b 
    // my_strlen("abc")
    // 1+my_strlen("bc")
    //1+1+my_strlen("c")
    //1+1+1+my_strlen("")
    //1+1+1+0
    //3
}
int main()
{
       char arr[] = "abc";
       // [a b c \0]
       int len = my_strlen(arr);// 数组名是首元素的地址 第一个元素的地址
       printf("%d\n", len);
       return 0;
}

分析一下

二  递归与迭代

1 求n的阶乘(不考虑溢出)

#include<stdio.h>
// 循环(迭代)
int fun(int n)
{
       int i = 0;
       int r = 1;
       for (i = 1; i <= n; i++)
       {
              r = r * i;
       }
       return r;
}
int main()
{
       int n = 0;
       scanf("%d", &n);
       int ret = fun(n);
       printf("%d\n", ret);
       return 0;
}
#include<stdio.h>
//递归
int fun(int n)
{
       if (n <= 1)
              return 1;
       else
              return n * fun(n - 1);
}
int main()
{
       int n = 0;
       scanf("%d", &n);
       int ret = fun(n);
       printf("%d\n", ret);
       return 0;
}

2 求第n个斐波那契数。(不考虑溢出)

//求第n个斐波那契数。(不考虑溢出)
// 1 1 2 3 5 8 13 .....
//前两个数的和是第三个数
#include<stdio.h>
int fib(int n)
{
       if (n <= 2)
              return 1;
       else
              return fib(n - 1) + fib(n - 2);
}
int main()
{
       int n = 0;
       scanf("%d", &n);
       int ret = fib(n);
       printf("%d\n", ret);
       return 0;
}

但是有个问题 我们输入数值较大的时候 计算机就吃不消了 虽然一直在跑 但是迟迟算不出来结果

 所以我们就要考虑迭代的方法了

#include<stdio.h>
// 循环(迭代)
int fib(int n)
{
       int a = 1;
       int b = 1;
       int c = 1;
       while (n >= 3)
       {
              c = a + b;
              a = b;
              b = c;
              n--;
       }
       return c;
}
int main()
{
       int n = 0;
       scanf("%d", &n);
       int ret = fib(n);
       printf("%d\n", ret);
       return 0;
}

1 + 1 = 2 (第三个数)

a + b = c

1 + 2 = 3 (第四个数)

b赋给a   c赋给b

2 + 3 = 5 (第五个数)

..........

1. 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。 

2. 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。 

3. 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开 销。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值