斐波那契数列

感谢大佬的光临各位,希望和大家一起进步,望得到你的三连,互三支持,一起进步

个人主页LaNzikinh-CSDN博客

收入专栏:初阶数据结构_LaNzikinh篮子的博客-CSDN博客

文章目录

  • 前言
  • 一.斐波那契数
  • 二.改循环
  • 三.尾递归
  • 总结

前言

很多人都对递归有了解,但是为尾递归很少,所以这次来专门讲一讲关于尾递归的一些问题。


一.斐波那契数

斐波那契数列(Fibonacci sequence),也称之为黄金分割数列,由意大利数学家列昂纳多・斐波那契(Leonardo Fibonacci)提出。 斐波那契数列指的是这样的一个数列:1、1、2、3、5、8、13、21、34、......,这个数列从第 3 项开始,每一项都等于前面两项之和。

那么如何用代码实现斐波那契数呢?

我们通常就是想到用递归的方法,因为这个也是最常见的方法,只要利用函数递归就可以直接使用,思想也很容易去想。

cpp 复制代码
long long Fid(int n)
{
    if (n <= 2)
        return 1;
    else
        return Fid(n - 1) + Fid(n - 2);
}



int main()
{
    int n = 0;
    int ret = 0;
    scanf_s("%d", &n);
    ret = Fid(n, 1, 1);
    printf("%d\n", ret);
    return 0;

    return 0;
}

但是存在问题,我们自己运行的时候也会发现这些问题,就是当数字大的时候就运行不了,非常的缓慢,那是因为递归多次调用函数,导致的栈溢出,所以我们改怎么修改代码呢?之前我们在改排序的时候也将递归改为非递归的形式,之前我们说过递归改非递归有两种改法,一种是改循环,还有一种就是通过数据结构来转换,我们之前的归并排序非递归就是通过改循环,这次就是通过栈,去搭建。但是这次我们不用数据结构去解决,而是用一种特殊的方法,尾递归


二.改循环

我们先来讲一下最基本的该法,也是我们都清楚的改法,改循坏内部

cpp 复制代码
long long Fid(int n)
{
    long long f1 = 1;
    long long f2 = 1;
    long long f3 = 0;
    for (int i = 3; i <= n; i++)
    {
        f3 = f1 + f2;
        f1 = f2;
        f2 = f3;
    }
    return f3;
   
}

int main()
{
    int n = 0;
    long long ret = 0;
    scanf_s("%d", &n);
    ret = Fid(n);
    printf("%lld\n", ret);
    return 0;
}

注意要开long long 因为在后面斐波那契数会越来越大,int很有可能不够用,所以我们就要用long long型来使用


三.尾递归

什么是尾递归

如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。因为在一些题目的做法中,我们可以发现递归的使用有局限性,有时候会占用相当大的空间。比如斐波那契问题,代码很容易用递归去写,但是浪费了大量的内存,一个数会重复计算多次,所以我们来使用尾递归。这里引用一个我看别人说的一句话,我认为非常对普通递归的结果是返回值,尾递归的结果是参数。完全可以这样理解。

尾递归的优化原理

尾递归优化的概念 尾递归是指递归调用出现在函数体的最后,并且是返回值的一部分。 它是一种特殊的递归形式,不会在回归过程中做其他操作或表达式的计算。尾调用优化 尾调用是尾递归优化的基础。 尾调用是指函数调用出现在调用者函数的最后,并且该调用的返回值直接被当前函数返回。 尾调用优化的目的是将递归调用转化为尾调用,从而减少函数调用栈的使用。 通过尾调用优化,实现函数的尾递归优化,可以避免递归调用带来的栈溢出问题。

然后我们来用尾递归的思路来实现一下斐波那契数的非递归做法

这里跟普通的相比也是多传两个参数,因为最开始的两个数都是1,我们必须提前知道,其实做法和普通方法的思维是一致的也是相加,但是最后需要用这个b来表示出来,用逗号表达式的这个知识和函数传参.

cpp 复制代码
int Fib(int n, int a, int b) 
{
    if (n < 3)
    {
        return b;
    }
    else
        return Fib(n - 1, b, a + b);
}

这是我以前写的代码,我们现在来优化一下

cpp 复制代码
long long Fib(int n, long long a, long long b)
{
    if (n < 3)
    {
        return b;
    }
    else
        return Fib(n - 1, b, a + b);
}

int main()
{
    int n = 0;
    long long ret = 0;
    scanf_s("%d", &n);
    ret = Fib(n,1,1);
    printf("%lld\n", ret);
    return 0;
}

总结

三种方法体验了代码的可玩性,这就是代码的魅力,真的非常有体会,所以分享一下

相关推荐
为什么这亚子44 分钟前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
1 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
幸运超级加倍~2 小时前
软件设计师-上午题-16 算法(4-5分)
笔记·算法
yannan201903132 小时前
【算法】(Python)动态规划
python·算法·动态规划
埃菲尔铁塔_CV算法2 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法
EasyCVR2 小时前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
linsa_pursuer2 小时前
快乐数算法
算法·leetcode·职场和发展
小芒果_012 小时前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
qq_434085902 小时前
Day 52 || 739. 每日温度 、 496.下一个更大元素 I 、503.下一个更大元素II
算法