首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 入門教學:函式遞迴呼叫機制與實戰範例

     編輯:PHP 綜合知識

遞迴 是函式直接或間接呼叫自身的技術,適合解決「問題可分解為相同性質的較小子問題」的場景:階乘、費波那契、樹狀結構遍歷、目錄遞迴掃描等。

遞迴三要素

  1. 基礎案例:終止條件,避免無限遞迴導致堆疊溢位。
  2. 遞迴步驟:將問題縮小並呼叫自身。
  3. 狀態傳遞:透過參數/返回值傳遞中間結果。

程式碼範例:遞迴輸出遞減數字

<?php
function abc($n) {
    if ($n > 2) {           // 遞迴條件
        abc(--$n);          // 遞迴呼叫 (前置遞減)
    }
    echo '$n=' . $n . "<br />";  // 每層返回時輸出
}
abc(4);
?>

執行流程圖解

abc(4)
  ├─ n=4 > 2 → abc(--n) → abc(3)
  │     ├─ n=3 > 2 → abc(--n) → abc(2)
  │     │     ├─ n=2 ≯ 2 → 輸出 $n=2 → 返回
  │     │     └─ 返回上層 → 輸出 $n=2 → 返回
  │     └─ 返回上層 → 輸出 $n=3 → 返回
  └─ 返回主程式 → 結束

輸出順序:
$n=2
$n=2
$n=3

關鍵觀察

  • --$n (前置遞減) 在呼叫前修改變數值,導致同一層級的兩次輸出皆為 2。
  • 若改用 abc($n - 1) (不修改原變數),輸出將為 2, 3, 4。
  • 遞迴深度受限於 xdebug.max_nesting_level (預設 256) 與記憶體限制;深度遞迴請改用迴圈或增加限制。

經典遞迴應用:階乘

<?php
function factorial($n) {
    if ($n <= 1) return 1;           // 基礎案例
    return $n * factorial($n - 1);   // 遞迴步驟
}
echo factorial(5);  // 120
?>

目錄遞迴掃描 (實務高頻)

<?php
function scanDir($path) {
    $items = scandir($path);
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') continue;
        $full = $path . DIRECTORY_SEPARATOR . $item;
        if (is_dir($full)) {
            echo "[DIR]  $full\n";
            scanDir($full);   // 遞迴進入子目錄
        } else {
            echo "[FILE] $full\n";
        }
    }
}
scanDir(__DIR__);
?>

遞迴 vs 迴圈 效能與適用性比較

維度遞迴迴圈
程式碼簡潔度高 (樹狀/分形問題)低 (需自維護堆疊)
記憶體消耗O(深度) 呼叫堆疊O(1) 常數空間
執行速度較慢 (函式呼叫開銷)較快
除錯難度較高 (堆疊追蹤)較低
適用場景樹/圖遍歷、分治演算法、語法解析線性處理、已知迴圈次數

尾端遞迴優化 (TCO) 提示

PHP 不支援 尾端遞迴優化,所有遞迴皆佔用堆疊幀。深度遞迴 (> 1000 層) 必須改寫為迴圈或使用 Generator / 手動堆疊模擬。

遞迴除錯技巧

  • 加入 debug_backtrace() 或 xdebug_var_dump() 觀察呼叫堆疊。
  • 設定 ini_set('xdebug.max_nesting_level', 500) 臨時放寬限制。
  • 使用 declare(ticks=1) + register_tick_function 監控遞迴深度。
  • 單元測試覆蓋基礎案例、邊界值 (0, 1, 負數)、一般值。

理解遞迴機制與 PHP 實作限制,能讓您在適合場景 (樹狀結構、分治演算法) 優雅解決問題,並在不適合場景果斷選擇迴圈替代。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved