【PHP】关于递归函数
这篇文章是「YYPHP Advent Calendar 2018」第13天的贴子。
虽然文笔不太好,但请多多关照 (_ _ (´ω` )ペコ
最初我打算发布一篇关于类、接口和特质的文章总结,但在研究“::”的访问时,我感到非常困惑,所以我决定彻底改变内容,给大家介绍递归函数(之前没有写过或发布过的)。
首先
本文适用于理解基本函数描述方法的人。
光看”递归函数”这个字面感觉难,但只要冷静地逐个看,就能理解。
由于我的知识有限,所以我可能会在解释中犯错误。
如果有任何错误,请指正我一下 (((o(´ω` )o)))
递归函数是指可以自我调用的函数。
递归这个词的意思是“再次回来”或者“再次返回”。
递归函数字面上就是指通过重复调用自身来执行的函数。
可能有些人会想,什么叫调用自己呢?
如果要用最简洁的方式来写递归函数,可以写成以下形式。
<?php
function abc($args) {
return abc($args -1); //abc 関数内で abc 関数を呼び出している
}
在 abc 函数内部调用了 abc 函数。
递归函数并没有特殊的语法,只是简单地调用相同的函数而已。
这种自己调用自己的函数被称为递归函数。
稍后会详细解释,但上述的代码是一个无限循环的代码,请不要尝试。
让我们通过观察实例来加深对递归函数的理解。这次我们想要创建一个用于计算阶乘的递归函数。
从根本上说,阶乘是什么?
我想有些人可能会忘记了阶乘的概念,或者还没有学过,所以我简单地解释一下。
一听到阶乘这个词,可能会觉得很难,但实际上就是按顺序相乘而已。
5的阶乘就是5乘以4乘以3乘以2乘以1,结果是120。
3的阶乘就是3乘以2乘以1,结果是6。
所谓阶乘,字面上就是成了一层(或者换句话说成一层一层加上去),只需要按顺序相乘即可。
求阶乘的方法有很多,只是不停地乘以减1的值。
这样的处理方式不需要使用递归函数也能写出来,但是使用递归函数可以更简单地进行描述。
如果将参数指定为3,就可以创建一个递归函数返回6。
阶乘计算的递归函数。
我們將創建一個名為factorial的遞歸函數來計算階乘。
<?php
function factorial($args) {
if($args > 0) {
return $args * factorial($args - 1);
}
return 1;
}
echo factorial(3); //表示結果は 6
如果阶乘函数的参数大于0,则执行 return $args * factorial($args – 1),如果小于0,则执行 return 1。
值得注意的是 factorial($args – 1) 这一部分。
因为在阶乘函数内部调用了阶乘函数,所以在这里又会执行阶乘函数。
然而,参数变成了 $args – 1,所以函数将以比初始参数少1的参数进行执行。
阶乘函数内部的阶乘函数内部又会执行阶乘函数。
由于在函数内部调用了相同的函数,因此会产生无限循环。
在初始说明中提到不要尝试无限循环是因为这个原因。
即使无法想象出处理的顺序,下面将进行解释。
为了避免无限循环,我们使用 if($args > 0) 条件进行指定。
如果这个条件成立,则调用相同的函数,但如果为假,则执行 return 1,函数将不再被调用。
在使用递归函数时,需要使用 if 来确保递归终止。
相信已经理解了如何编写递归函数。
接下来我们来看看递归函数是如何处理的。
在中文中,递归函数如何处理?
递归函数是将函数嵌套调用的过程。在阶乘函数内部调用了阶乘函数,而在阶乘函数内部的阶乘函数又调用了阶乘函数,无限地重复调用相同的函数。可以想象成以下的过程。
由于递归函数无限循环,所以我们使用 if 条件来指定结束条件。在这种情况下,如果参数小于 0,则 factorial 函数将不执行并返回 1。
如果用代码强行表示这个递归函数的话,可以有以下的想法。
函数以嵌套的方式按顺序执行。
正如你所看到的,递归函数并没有进行复杂的操作。
通过逐个检查嵌套的函数,我们可以理解它们是如何被处理的。
首先执行①。
由于条件不符合,因此执行 return 1,在①中最终返回值为1。
接下来将执行第二步。
由于满足了if条件,将执行return 1 * 1,并在第二步中最终返回了值1。
然后执行第3个步骤。
由于第3个步骤也满足了条件,所以执行了return 2 * 1,最终在第3个步骤中返回了值2。
由于条件满足,最后执行了函数④,并返回了结果6。
在递归函数中,函数会按顺序执行相同的函数。
最终 / 最后
我希望你已经理解了递归函数的行为。
另外,我还整理了一些与PHP相关的文章,如果你有兴趣的话可以看一下。
“超入门”并不是指深入入门,而是指为初学者(指的是我自己)详细冗长地解释的入门级文章。
-
- Qiita – 【PHP超入門】式・文・構文・言語構造・制御構造について
-
- Qiita – 【PHP超入門】値の代入と値渡しについて
-
- Qiita – 【PHP超入門】参照(リファレンス)の代入について
-
- Qiita – 【PHP超入門】HTTP(GET・POST)について
-
- Qiita – 【PHP超入門】Cookieとセッションについて
-
- Qiita – 【PHP超入門】クラス~例外処理~PDOの基礎
- Qiita – 【PHP超入門】名前空間(namespace・use)について
希望這篇文章能夠增進初學者對主題的理解。非常感謝您把文章讀完至末尾。
明天的圣诞节日历是由@okashoi的文章。由于还有其他与PHP相关的圣诞节日历,如果您感兴趣的话,请随意查看。
PHP相关的圣诞节日历
-
- PHP Advent Calendar 2018 – Qiita
-
- PHPで学ぶデザインパターン Advent Calendar 2018 – Qiita
-
- PHP-MASTER-CHANGES Advent Calendar 2018 – Qiita
-
- CakePHP Advent Calendar 2018 – Qiita
-
- Laravel Advent Calendar 2018 – Qiita
-
- Laravel #2 Advent Calendar 2018 – Qiita
- Symfony Advent Calendar 2018 – Qiita
请注意
请注意,我发表了一篇文章,有兴趣的人可以去看看。
“让我们一起阅读初学者友好的PHP TODO应用程序的代码”