数据结构-算法

斐波那契数列递归与非递归算法时间复杂度分析

斐波那契数列定义:
F(n)={0,n=01,n=1F(n−1)+F(n−2),n>1 F(n)= \begin{cases} 0, & n=0 \\ 1, & n=1 \\ F(n-1)+F(n-2), & n>1 \end{cases} F(n)=⎩ ⎨ ⎧0,1,F(n−1)+F(n−2),n=0n=1n>1


一、递归算法的时间复杂度分析

1. 算法逻辑

直接按照数学定义实现,每次计算F(n)时,递归调用F(n-1)F(n-2),直到递归到基线条件n=0n=1

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

// 递归实现斐波那契数列
long long fib_recursive(int n) {
    // 基线条件:n=0 返回0,n=1 返回1
    if (n == 0) return 0;
    if (n == 1) return 1;
    // 递归调用:F(n) = F(n-1) + F(n-2)
    return fib_recursive(n - 1) + fib_recursive(n - 2);
}

int main() {
    int n;
    printf("请输入要计算的斐波那契数列项数 n:");
    scanf("%d", &n);

    if (n < 0) {
        printf("请输入非负整数!\n");
        return 1;
    }

    printf("递归版:F(%d) = %lld\n", n, fib_recursive(n));
    return 0;
}

2. 时间复杂度递推关系

T(n)为计算F(n)的时间开销:

  • 基线条件:n=0/n=1时,直接返回结果,时间为常数,即T(0)=T(1)=O(1)
  • 递归条件:n>1时,需执行2次递归调用(T(n-1)+T(n-2))+1次加法(常数时间O(1)),递推式为:
    T(n)=T(n−1)+T(n−2)+O(1) T(n) = T(n-1) + T(n-2) + O(1) T(n)=T(n−1)+T(n−2)+O(1)

3. 递推式求解

该递推式的特征方程为r² - r - 1 = 0,解得特征根:
r1=1+52≈1.618 (黄金分割比 ϕ),r2=1−52≈−0.618 r_1 = \frac{1+\sqrt{5}}{2} \approx 1.618 \ (\text{黄金分割比}\ \phi),\quad r_2 = \frac{1-\sqrt{5}}{2} \approx -0.618 r1=21+5 ≈1.618 (黄金分割比 ϕ),r2=21−5 ≈−0.618

通解为T(n) = A·r₁ⁿ + B·r₂ⁿ,代入初始条件后可得:T(n)与斐波那契数列F(n)同阶,因此时间复杂度为:
T(n)=O(ϕn)=O(2n) (指数级时间复杂度) \boldsymbol{T(n) = O(\phi^n) = O(2^n)} \ (\text{指数级时间复杂度}) T(n)=O(ϕn)=O(2n) (指数级时间复杂度)

4. 空间复杂度

递归调用会产生调用栈,最大深度为n(从F(n)F(1)的递归链),因此空间复杂度为O(n)


二、非递归(迭代)算法的时间复杂度分析

1. 算法逻辑

从基线条件F(0)=0F(1)=1出发,通过循环依次计算F(2)F(n),每次仅保存前两项的值,无重复计算。

c 复制代码
#include <stdio.h>

// 迭代实现斐波那契数列
long long fib_iterative(int n) {
    // 边界处理
    if (n == 0) return 0;
    if (n == 1) return 1;

    long long a = 0;  // F(0)
    long long b = 1;  // F(1)
    long long c;      // 存储当前计算结果

    // 循环从 2 计算到 n
    for (int i = 2; i <= n; i++) {
        c = a + b;    // F(i) = F(i-1) + F(i-2)
        a = b;        // 更新前一项
        b = c;        // 更新当前项
    }
    return c;
}

int main() {
    int n;
    printf("请输入要计算的斐波那契数列项数 n:");
    scanf("%d", &n);

    if (n < 0) {
        printf("请输入非负整数!\n");
        return 1;
    }

    printf("迭代版:F(%d) = %lld\n", n, fib_iterative(n));
    return 0;
}

2. 时间复杂度分析

循环从i=2执行到i=n,共执行n-1次,每次循环仅包含常数时间的加法、赋值操作,因此时间复杂度为:
T(n)=O(n) (线性时间复杂度) \boldsymbol{T(n) = O(n)} \ (\text{线性时间复杂度}) T(n)=O(n) (线性时间复杂度)

3. 空间复杂度

仅使用3个变量存储中间结果(F(i-2)F(i-1)F(i)),与n无关,因此空间复杂度为O(1)(常数空间)。


三、两种算法的核心对比

算法类型 时间复杂度 空间复杂度 核心特点
递归算法 O(ϕn)O(\phi^n)O(ϕn)(指数级,近似O(2n)O(2^n)O(2n)) O(n)O(n)O(n)(递归栈) 实现直观,但存在大量重复计算(如F(n-2)F(n)F(n-1)重复计算),仅适合理论分析,工程中不可用
非递归(迭代)算法 O(n)O(n)O(n)(线性级) O(1)O(1)O(1)(常数空间) 无重复计算,时间/空间效率极高,是工程实践的首选方案

补充:递归算法的优化(记忆化搜索)

若对递归算法添加「备忘录」(存储已计算的F(k),避免重复计算),可将时间复杂度优化为O(n),但空间复杂度仍为O(n)(存储备忘录),整体效率仍低于迭代算法。


关键结论

  • 朴素递归算法是指数时间 ,仅适合教学演示,无法处理较大的n
  • 迭代算法是线性时间+常数空间,是斐波那契数列计算的最优工程实现。

线性表的基本操作分析

c 复制代码
#include <stdio.h>

// test函数:参数为int类型,采用值传递
void test(int x) {
    x = 1024;          // 修改的是形参x(main中x的副本)
    printf("test函数内部 x=%d\n", x);
}

int main() {
    int x = 1;
    printf("调用test前 x=%d\n", x);
    test(x);           // 传递x的值1,形参是独立副本
    printf("调用test后 x=%d\n", x); // main中x不会被修改
    return 0;
}
c 复制代码
调用test前 x=1
test函数内部 x=1024
调用test后 x=1

C 语言默认是值传递:

调用test(x)时,系统为形参x分配独立内存,把main中x的值1复制给形参。

test内修改的是形参副本,和main中的x是两个完全独立的变量,因此main中的x不会改变。

c 复制代码
#include <stdio.h>

// test函数:参数为int*类型,传递x的内存地址
void test(int *x) {
    *x = 1024;         // 通过地址直接修改main中x的值
    printf("test函数内部 x=%d\n", *x);
}

int main() {
    int x = 1;
    printf("调用test前 x=%d\n", x);
    test(&x);          // 传递x的地址&x
    printf("调用test后 x=%d\n", x); // main中x被修改为1024
    return 0;
}
c 复制代码
调用test前 x=1
test函数内部 x=1024
调用test后 x=1024
相关推荐
方便面不加香菜4 小时前
Linux--基础IO(一)
linux·运维·服务器
mounter6259 小时前
现代 Linux 内存管理的演进与变革:从传统 LRU 到多代架构 MGLRU
linux·服务器·kernel
赵渝强老师9 小时前
【赵渝强老师】Kubernetes(K8s)中的金丝雀升级
linux·docker·云原生·容器·kubernetes
Qt程序员10 小时前
Linux RCU 原理与应用
linux·c++·内核·linux内核·rcu
The Sheep 202310 小时前
Vue复习
linux·服务器·数据库
兄台の请冷静10 小时前
Linux 安装es
linux·elasticsearch·jenkins
fengyehongWorld10 小时前
Linux rg命令
linux
pride.li10 小时前
海思视觉Hi3516CV610--开机自动设置ip
linux·网络·网络协议·tcp/ip
我叫张小白。10 小时前
CentOS 7 安装 Docker并配置镜像加速(完整指南)
linux·docker·centos
Titan202412 小时前
Linux动静态库
linux·服务器·c++