# 遞迴
## 1. 什麼是遞迴?
遞迴(Recursion)是一種程式設計技巧,函式會在其內部直接或間接呼叫自己。適用於問題可拆解為較小的相同問題,如數學計算、搜尋與排序。
## 2. 遞迴函式的結構
```cpp=
返回類型 函式名稱(參數) {
// 終止條件
if (條件滿足) {
return 結果;
}
// 遞迴呼叫
return 函式名稱(新參數);
}
```
**終止條件:** 確保遞迴不會無限執行,一定要加,不然妳可以試試,~~放心不會試試就逝世~~。
**遞迴步驟:** 逐步將問題縮小,直到符合終止條件。
## 3. 遞迴範例
### 費氏數列
#### 什麼是**費式數列**
由數學家**列昂納多·費波那契**(Leonardo Fibonacci)提出的數列,其特點是**每一項數字**都是**前兩項數字的和**。這個數列通常以 0 和 1 開始,之後的數字依照規則生成。
數列的數字如下所示: $0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...$
費式數列的定義:
$F(0) = 0$
$F(1) = 1$
$F(n) = F(n-1) + F(n-2) (n ≥ 2)$
##### 特點:
每個數字都是前兩個數字的和。
#### eg.
```cpp=
#include <iostream>
using namespace std;
int f(int n) {
if (n <= 1) return n; // 終止條件
return f(n - 1) + f(n - 2); // 遞迴步驟
}
int main() {
int n = 5;
cout << "F(n) = " << f(n) << endl;
return 0;
}
```
** 輸出:**
```
F(5) = 5
```
### 階乘計算
這我應該不用多說吧!!
```cpp
#include <iostream>
using namespace std;
int f(int n) {
if (n == 0) return 1; // 終止條件
return n * f(n - 1); // 遞迴步驟
}
int main() {
int n = 5;
cout << "F(n) = " << f(n) << endl;
return 0;
}
```
** 輸出:**
```
F(5) = 120
```
## 4. 遞迴與迴圈的比較
| 比較項目 | 遞迴 | 迴圈 |
|----------|------|------|
| 可讀性 | 適合數學遞推問題 | 適合重複執行的邏輯 |
| 記憶體使用 | 可能較高(因為使用堆疊) | 佔用較少記憶體 |
| 效率 | 可能較低(函式呼叫有額外開銷) | 通常較快 |
## 5. 遞迴的應用
- **數學運算**:費氏數列、階乘、歐幾里得算法,甚至是河內塔問題都可以。
- **資料結構**:樹(Tree)、圖(Graph)的遍歷。
- **演算法**:合併排序(Merge Sort)、快速排序(Quick Sort)。
## 6. 結論
遞迴是一種強大的程式設計工具,適合解決可拆解為較小子問題的情境。但是,如果沒有妥善設定終止條件,可能導致無窮遞迴與記憶體溢位(Stack Overflow)。適時選擇迴圈或遞迴,能夠提升程式的效能與可讀性。
:::success
上面提到的 Stack Overflow 在記憶體分布有做介紹,他和資料結構的 stack 沒有什麼太大關係,所以不要誤會了。
:::