F(1)=1, F(2)=1, F(n)=F(n-1)+F(n-2) (n>2)
前 10 項:1, 1, 2, 3, 5, 8, 13, 21, 34, 55
為避免指數級時間複雜度 (朴素遞迴 `fib(n)=fib(n-1)+fib(n-2)` 會重複計算),採用 **尾遞迴** 攜帶前兩項數值與計數器:
#include
/**
* 尾遞迴輸出費波那契數列
* @param x 前一項數值 (初始為 1)
* @param y 當前項數值 (初始為 1)
* @param acc 已輸出項數 (初始為 1)
*/
void printFibRecursive(int x, int y, int acc) {
// 終止條件:已輸出 10 項
if (acc > 10) return;
// 輸出當前項 (x 代表 F(acc))
printf("%d ", x);
// 遞迴呼叫:下一項為 y,再下一項為 x+y,計數器+1
printFibRecursive(y, x + y, acc + 1);
}
int main() {
// 起始呼叫:F(1)=1, F(2)=1, 已輸出第 1 項
printFibRecursive(1, 1, 1);
printf("\n");
return 0;
}
| 呼叫層級 | x (輸出值) | y (下一項) | acc | 動作 |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 印 1 → 遞迴(1, 2, 2) |
| 2 | 1 | 2 | 2 | 印 1 → 遞迴(2, 3, 3) |
| 3 | 2 | 3 | 3 | 印 2 → 遞迴(3, 5, 4) |
| 4 | 3 | 5 | 4 | 印 3 → 遞迴(5, 8, 5) |
| 5 | 5 | 8 | 5 | 印 5 → 遞迴(8, 13, 6) |
| 6 | 8 | 13 | 6 | 印 8 → 遞迴(13, 21, 7) |
| 7 | 13 | 21 | 7 | 印 13 → 遞迴(21, 34, 8) |
| 8 | 21 | 34 | 8 | 印 21 → 遞迴(34, 55, 9) |
| 9 | 34 | 55 | 9 | 印 34 → 遞迴(55, 89, 10) |
| 10 | 55 | 89 | 10 | 印 55 → 遞迴(89, 144, 11) |
| 11 | - | - | 11 | acc>10 返回,遞迴結束 |
1 1 2 3 5 8 13 21 34 55
int fib(int n) {
if (n <= 2) return 1;
return fib(n-1) + fib(n-2); // 指數複雜度,僅供教學
}
// 尾遞迴優化版
int fibTail(int n, int a, int b) {
if (n == 1) return a;
if (n == 2) return b;
return fibTail(n-1, b, a+b);
}
// 呼叫: fibTail(10, 1, 1) -> 55
使用**尾遞迴累加器模式**可在符合「純遞迴、無迴圈」限制下,以 **O(n) 時間** 高效輸出費波那契數列。關鍵在於將「狀態」 (前兩項值、計數器) 作為參數傳遞,而非依賴全域變數或重複計算。