1斐波那契数列的定义
斐波那契数列(Fibonacci sequence),又称黄金分割数列,是由意大利数学家莱昂纳多·斐波那契(Leonardo Fibonacci)在1202年提出的。其核心定义为:
-
首项(第1项)和第2项均为1;
-
从第3项开始,每一项都等于它前两项的和。
用数学公式可表示为:
F(1) = 1,F(2) = 1
F(n) = F(n-1) + F(n-2) (其中n ≥ 3,n为正整数)
根据定义,斐波那契数列的前10项为:1, 1, 2, 3, 5, 8, 13, 21, 34, 55...
2 迭代实现
思路:通过循环迭代,用变量保存前两项的值,依次计算出当前项,避免重复计算,效率大幅提升。
cpp
//迭代实现斐波那契数列
#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 b = fib(n);
printf("%d", b);
return 0;
}

3 递归实现
cpp
#include <stdio.h>
// 递归实现斐波那契数列
int fib_recursion(int n) {
// 边界条件:处理n≤0的非法输入
if (n <= 0) {
printf("输入错误,n必须为正整数!\n");
return -1;
}
// 递归终止条件:第1项和第2项均为1
if (n == 1 || n == 2) {
return 1;
}
// 递归公式:F(n) = F(n-1) + F(n-2)
return fib_recursion(n - 1) + fib_recursion(n - 2);
}
int main() {
int n = 0;
printf("请输入要计算的斐波那契数列项数:");
scanf("%d", &n);
int result = fib_recursion(n);
if (result != -1) {
printf("斐波那契数列第%d项是:%d\n", n, result);
}
return 0;
}
优缺点:
优点:代码简洁直观,直接映射数学定义,易于理解;
缺点:效率极低,存在大量重复计算(例如计算F(5)时,会重复计算F(3)、F(2)等),当n较大(如n>30)时,运行时间会显著增加,甚至出现卡顿。
3 用尾递归怎样实现
先理解:什么是尾递归?
尾递归是递归的一种特殊形式:
- 普通递归:函数最后一步是调用自身 + 其他运算 (比如
return fib(n-1) + fib(n-2)),会产生大量重复计算,且需要保存多层调用栈。 - 尾递归:函数最后一步只有自身调用,没有额外运算,编译器 / 解释器可优化为迭代(复用栈帧),效率和迭代几乎一致。
实现尾递归的关键:用参数保存中间结果,而非在递归返回后做加法运算。
cpp
#include <stdio.h>
// 核心尾递归函数(辅助函数)
// a: 保存前前项(初始为第1项 1)
// b: 保存前一项(初始为第2项 1)
// n: 剩余需要计算的项数
int fib_tail_recursion_helper(int a, int b, int n) {
// 递归终止条件:剩余项数为0,返回当前的前一项(即目标项)
if (n == 0) {
return a;
}
// 尾递归调用:仅更新参数,无额外运算
// a 变为原b,b 变为 a+b(当前项),剩余项数n-1
return fib_tail_recursion_helper(b, a + b, n - 1);
}
// 对外暴露的函数(封装尾递归,简化调用)
int fib_tail_recursion(int n) {
// 1. 处理非法输入
if (n <= 0) {
printf("输入错误!n必须是正整数\n");
return -1;
}
// 2. 边界条件:第1、2项直接返回1
if (n == 1 || n == 2) {
return 1;
}
// 3. 调用尾递归辅助函数(初始参数适配n≥3的情况)
// 初始a=1(第1项)、b=1(第2项),剩余计算n-2项(因为前2项已确定)
return fib_tail_recursion_helper(1, 1, n - 2);
}
// 主函数测试
int main() {
int n = 0;
printf("请输入要计算的斐波那契数列项数:");
scanf("%d", &n);
int result = fib_tail_recursion(n);
if (result != -1) {
printf("斐波那契数列第%d项是:%d\n", n, result);
}
return 0;
}