一、定義簡述
- 遞歸:函數在執行過程中調用自身,通過不斷縮小問題規模,最終達到一個“基準條件”後返回。
- 迭代:通過循環結構(如
for、while)重複執行一段代碼,直到滿足退出條件。
二、優缺點對比
|
維度
|
遞歸(Recursion)
|
迭代(Iteration)
|
|
代碼可讀性 |
✅ 通常更簡潔、直觀,尤其適合具有自相似結構的問題(如樹、圖、分治)
|
❌ 有時邏輯較複雜,需要手動維護狀態
|
|
執行效率 |
❌ 函數調用有開銷(壓棧/出棧),時間與空間複雜度通常更高
|
✅ 效率高,無額外函數調用開銷
|
|
內存消耗 |
❌ 每次調用都會佔用棧空間,深度過大易導致 |
✅ 僅使用常量或少量變量,內存佔用低
|
|
適用場景 |
✅ 樹遍歷、回溯、分治、數學定義(階乘、斐波那契)、漢諾塔等
|
✅ 簡單計數、累加、數組遍歷等線性任務
|
|
調試難度 |
❌ 調用棧深,調試和追蹤較困難
|
✅ 狀態清晰,易於單步調試
|
|
尾遞歸優化支持 |
⚠️ Java、Python 等主流語言不支持自動尾遞歸優化 (Scala、Erlang、Haskell 等函數式語言支持)
|
不適用
|
三、實例對比:計算階乘
遞歸實現
public static int factorialRec(int n) {
if (n <= 1) return 1;
return n * factorialRec(n - 1);
}
迭代實現
public static int factorialIter(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
✅ 結論:
- 遞歸代碼更貼近數學定義,易理解;
- 迭代效率更高,且不會棧溢出。
四、何時選擇遞歸?何時選擇迭代?
優先使用 遞歸 的情況:
- 問題天然具有遞歸結構(如二叉樹、圖的深度優先搜索)
- 使用回溯算法(如全排列、N皇后)
- 分治策略(如歸併排序、快速排序)
- 代碼簡潔性比性能更重要(如原型開發、教學演示)
優先使用 迭代 的情況:
- 問題可通過簡單循環解決(如求和、查找、遍歷數組)
- 對性能或內存有嚴格要求
- 遞歸深度不可控(如處理大規模輸入)
- 目標平台不支持深層遞歸(如嵌入式系統)
五、補充:遞歸轉迭代的技巧
很多遞歸算法可以通過顯式使用棧(Stack) 轉換為迭代形式。例如:
- 二叉樹的前序遍歷(遞歸 → 用 Stack 模擬)
- DFS(深度優先搜索)可用 Stack 實現
- 尾遞歸可直接改寫為 while 循環
💡 經驗法則:如果遞歸只有一次自我調用(如階乘),通常容易轉為迭代;如果有多個分支(如斐波那契、樹遍歷),轉換會更復雜。