PHP資料結構基礎之遞歸
這篇文章主要介紹了關於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。如果不符合這個條件,我們回傳n
乘 factorial(n)
,這符合遞迴特性的第一條和第三條。我們避免了循環調用,因為我們把每一次的遞歸調用都分解成了大問題的一個小的子問題。上面的演算法思想可以表達成:
遞迴Vs迭代
上面的遞歸程式碼我們同樣可以用迭代的方法實作
function factorial(int $n): int { $result = 1; for ($i = $n; $i > 0; $i--) { $result*= $n; } return $result; }
如果一個問題可以很容易的使用迭代來解決,我們為何要使用遞歸?
遞歸是用來處理更複雜的問題的,不是所有的問題都可以簡單的使用迭代來解決的。遞歸使用函數呼叫來管理呼叫棧,所以相比於迭代遞歸會使用更多和時間以及記憶體。此外,在迭代中,我們每一步都會有一個結果,但是在遞迴中我們必須等到base case執行結束才會有任何結果。看上面的例子,我們發現在遞歸演算法中我們沒有任何變數或聲明來保存結果,而在迭代演算法中,我們每次都用$result來保存了回傳結果。
斐波那契數列
在數學中,斐波那契數列是一個特殊的整數數列,數列中的每一個數的是由另外兩個數求和產生的。規則如下:
function fibonacci($n) { if ($n == 0) { return 0; } if ($n == 1) { return 1; } return fibonacci($n - 1) + fibonacci($ - 2); }
最大公因數
#另外一個使用遞迴演算法的常見問題是求兩個數的最大公因數。
function gcd(int $a, int $b) { if ($b == 0) { return $a; } return gcd($b, $a % $b); }
遞迴型別
#線性遞迴
在每一次遞迴呼叫中,函數只呼叫自己一次,這就叫做線性遞歸。
二分遞迴
在二分遞迴中,每一次遞迴呼叫函數都會呼叫自己兩次。求解斐波那契數列的演算法就是二分遞歸,除此之外還有二分查找、分治演算法、歸併排序等也使用了二分遞歸。
尾遞歸
當一個遞迴回傳的時候沒有等待的操作的時候就稱為尾遞歸。在斐波那契演算法中,回傳值需要乘以前一個遞歸的回傳值,因此他不是尾遞歸,而解出最大公因式的演算法就是尾遞歸。尾遞歸是線性遞歸的一種形式。
相互遞歸
例如在每一次遞歸呼叫中有A() 呼叫B(), B() 呼叫A() ,這樣的遞歸就叫做相互遞歸。
巢狀遞迴
當一個遞迴函數把自己當作一個參數進行遞迴呼叫時,就叫做巢狀遞歸。一個常見的栗子就是阿克曼函數,看下面的表達。
看最後一行的,可以看到第二個參數就是遞迴函數自己。
下一節
下一篇內容會使用遞歸解決一些實際開發中會遇到的問題,例如建立N級分類、建立嵌套評論、目錄檔案的遍歷等等。
以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!
相關推薦:
以上是PHP資料結構基礎之遞歸的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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

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