目錄
什麼是遞歸?
一個栗子
遞迴演算法的特性
" >遞迴Vs迭代PHP資料結構基礎之遞歸
斐波那契數列
最大公因數
遞迴型別
下一節
首頁 後端開發 php教程 PHP資料結構基礎之遞歸

PHP資料結構基礎之遞歸

Jul 07, 2018 pm 03:29 PM
遞迴 遞迴調用

這篇文章主要介紹了關於PHP資料結構基礎之遞歸,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

什麼是遞歸?

之前說到,遞歸是一種將大問題分解為小問題的解決方案。一般來說,遞歸稱為函數自身的呼叫。這麼說可能聽起來很奇怪,事實上在遞歸中,函數確實必須呼叫自己。

一個栗子

例如在數學中,我們都知道「階乘」的概念。例如5的階乘就是5*4*3*2*1

  • 5! = 5 * 4!

  • 4! = 4 * 3!

  • 3! = 3 * 2!

  • 2! = 2 * 1!

  • 1! = 1 * 0!

  • 0! = 1

我們可以總結求n的階乘的規律,即 n! = n * (n -1) !

這就體現了遞迴。你可以從中發現,我們把求5的階乘一步一步轉化成了另外一個個的小問題。

遞迴演算法的特性

  • 每一個遞迴呼叫都必須基於一個小的子問題。例如5的階乘就是5乘4的階乘。

  • 遞迴必須有一個Base case。例如階乘的Base case就是0,當條件是0的時候,就停止遞歸。

  • 遞歸中避免循環調用,否則最後電腦會顯示堆疊溢出的錯誤。

function factorial(int $n): int
{
    if ($n = 0) {
        return 1;
    }
    
    return $n * factorial($n - 1);
}
登入後複製

看上面的程式碼,我們可以看到對於階乘問題的解我們有一個基礎的條件就是當n為0的時候,我們回傳1。如果不符合這個條件,我們回傳nfactorial(n) ,這符合遞迴特性的第一條和第三條。我們避免了循環調用,因為我們把每一次的遞歸調用都分解成了大問題的一個小的子問題。上面的演算法思想可以表達成:

遞迴Vs迭代PHP資料結構基礎之遞歸

上面的遞歸程式碼我們同樣可以用迭代的方法實作

function factorial(int $n): int
{
    $result = 1;
    
    for ($i = $n; $i > 0; $i--) {
        $result*= $n;
    }
    
    return $result;
}
登入後複製

如果一個問題可以很容易的使用迭代來解決,我們為何要使用遞歸?

遞歸是用來處理更複雜的問題的,不是所有的問題都可以簡單的使用迭代來解決的。遞歸使用函數呼叫來管理呼叫棧,所以相比於迭代遞歸會使用更多和時間以及記憶體。此外,在迭代中,我們每一步都會有一個結果,但是在遞迴中我們必須等到base case執行結束才會有任何結果。看上面的例子,我們發現在遞歸演算法中我們沒有任何變數或聲明來保存結果,而在迭代演算法中,我們每次都用$result來保存了回傳結果。

斐波那契數列

在數學中,斐波那契數列是一個特殊的整數數列,數列中的每一個數的是由另外兩個數求和產生的。規則如下:

PHP資料結構基礎之遞歸

function fibonacci($n)
{
    if ($n == 0) {
        return 0;
    }
    
    if ($n == 1) {
        return 1;
    }
    
    return fibonacci($n - 1) + fibonacci($ - 2);
}
登入後複製

最大公因數

#另外一個使用遞迴演算法的常見問題是求兩個數的最大公因數。

PHP資料結構基礎之遞歸

function gcd(int $a, int $b)
{
    if ($b == 0) {
        return $a;
    }
    
    return gcd($b, $a % $b);
}
登入後複製

遞迴型別

  • #線性遞迴

在每一次遞迴呼叫中,函數只呼叫自己一次,這就叫做線性遞歸。

  • 二分遞迴

在二分遞迴中,每一次遞迴呼叫函數都會呼叫自己兩次。求解斐波那契數列的演算法就是二分遞歸,除此之外還有二分查找、分治演算法、歸併排序等也使用了二分遞歸。

  • 尾遞歸

當一個遞迴回傳的時候沒有等待的操作的時候就稱為尾遞歸。在斐波那契演算法中,回傳值需要乘以前一個遞歸的回傳值,因此他不是尾遞歸,而解出最大公因式的演算法就是尾遞歸。尾遞歸是線性遞歸的一種形式。

  • 相互遞歸

例如在每一次遞歸呼叫中有A() 呼叫B(), B() 呼叫A() ,這樣的遞歸就叫做相互遞歸。

  • 巢狀遞迴

當一個遞迴函數把自己當作一個參數進行遞迴呼叫時,就叫做巢狀遞歸。一個常見的栗子就是阿克曼函數,看下面的表達。

PHP資料結構基礎之遞歸

看最後一行的,可以看到第二個參數就是遞迴函數自己。

下一節

下一篇內容會使用遞歸解決一些實際開發中會遇到的問題,例如建立N級分類、建立嵌套評論、目錄檔案的遍歷等等。

以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!

相關推薦:

PHP取得客戶端真實IP位址的方法

PHP中使用Elasticsearch的方法

以上是PHP資料結構基礎之遞歸的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

C++ 函式的遞歸實作:遞迴深度有限制嗎? C++ 函式的遞歸實作:遞迴深度有限制嗎? Apr 23, 2024 am 09:30 AM

C++函數的遞歸深度受到限制,超過此限制會導致堆疊溢位錯誤。限制值因係統和編譯器而異,通常在1000到10000之間。解決方法包括:1.尾遞歸最佳化;2.尾呼叫;3.迭代實作。

C++ lambda 表達式是否支援遞迴? C++ lambda 表達式是否支援遞迴? Apr 17, 2024 pm 09:06 PM

是的,C++Lambda表達式可以透過使用std::function支援遞歸:使用std::function捕捉Lambda表達式的參考。透過捕獲的引用,Lambda表達式可以遞歸呼叫自身。

C++ 函式的遞迴實作:遞迴與非遞迴演算法的比較分析? C++ 函式的遞迴實作:遞迴與非遞迴演算法的比較分析? Apr 22, 2024 pm 03:18 PM

遞歸演算法透過函數自呼叫解決結構化的問題,優點是簡潔易懂,缺點是效率較低且可能發生堆疊溢位;非遞歸演算法透過明確管理堆疊資料結構避免遞歸,優點是效率更高且避免堆疊溢出,缺點是程式碼可能更複雜。選擇遞歸或非遞歸取決於問題和實現的特定限制。

在Java中遞歸地計算子字串出現的次數 在Java中遞歸地計算子字串出現的次數 Sep 17, 2023 pm 07:49 PM

給定兩個字串str_1和str_2。目標是使用遞歸過程計算字串str1中子字串str2的出現次數。遞歸函數是在其定義中呼叫自身的函數。如果str1是"Iknowthatyouknowthatiknow",str2是"know"出現次數為-3讓我們透過範例來理解。例如輸入str1="TPisTPareTPamTP",str2="TP";輸出Countofoccurrencesofasubstringrecursi

遞歸程式在C++中找到陣列的最小和最大元素 遞歸程式在C++中找到陣列的最小和最大元素 Aug 31, 2023 pm 07:37 PM

我們以整數數組Arr[]作為輸入。目標是使用遞歸方法在陣列中找到最大和最小的元素。由於我們使用遞歸,我們將遍歷整個數組,直到達到長度=1,然後返回A[0],這形成了基本情況。否則,將當前元素與當前最小或最大值進行比較,並透過遞歸更新其值以供後續元素使用。讓我們來看看這個的各種輸入輸出場景−輸入 −Arr={12,67,99,76,32};輸出 −數組中的最大值:99解釋 &mi

C++ 遞歸進階:瞭解尾遞歸最佳化及其應用 C++ 遞歸進階:瞭解尾遞歸最佳化及其應用 Apr 30, 2024 am 10:45 AM

尾遞歸最佳化(TRO)可提高特定遞歸呼叫的效率。它將尾遞歸呼叫轉換為跳轉指令,並將上下文狀態保存在暫存器中,而不是堆疊上,從而消除對堆疊的額外呼叫和返回操作,提高演算法效率。利用TRO,我們可以針對尾遞歸函數(例如階乘計算)進行最佳化,透過將tail遞歸呼叫替換為goto語句,編譯器會將goto跳轉移化為TRO,最佳化遞歸演算法的執行。

C++ 函式遞歸詳解:遞迴在字串處理中的應用 C++ 函式遞歸詳解:遞迴在字串處理中的應用 Apr 30, 2024 am 10:30 AM

遞歸函數是一種在字串處理中反覆呼叫自身來解決問題的技術。它需要一個終止條件以防止無限遞歸。遞歸在字串反轉和回文檢查等操作中被廣泛使用。

C++ 函式遞歸詳解:尾遞歸最佳化 C++ 函式遞歸詳解:尾遞歸最佳化 May 03, 2024 pm 04:42 PM

遞歸定義及最佳化:遞歸:函數內部呼叫自身,解決可分解為更小子問題的難題。尾遞歸:函數進行所有計算後才進行遞歸調用,可最佳化為循環。尾遞歸最佳化條件:遞歸呼叫為最後操作。遞歸呼叫參數與原始呼叫參數相同。實戰範例:計算階乘:輔助函數factorial_helper實現尾遞歸最佳化,消除呼叫棧,提高效率。計算斐波那契數列:尾遞歸函數fibonacci_helper利用最佳化,高效率計算斐波那契數。

See all articles