1.
程序调用自身的编程技巧称为递归( recursion)
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的 问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语 句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足 时,递归返回。
(1) 递归就是在过程或
函数里调用自身;
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口
2.
递归算法一般用于解决三类问题:
(1)数据的定义是按递归定义的。(Fibonacci
函数)
(2)问题解法按
递归算法实现。(回溯)
(3)数据的结构形式是按递归定义的。(
树的遍历,图的搜索)
3,缺点
递归的缺点:
递归算法解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的
算法或者某种特定情况,递归更为·
适合的时候。在
递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成
栈溢出等。
<?php
Function Test() {
static $count = 0; //静态变量只在首次调用时初始化,并被保持直到脚本运行结束
$count++;
echo $count;
if($count < 10){
Test();
}
$count--;//返回的时候静态变量清零
}
?>
<?php
//test() 与 test1() 等价
Function Test() {
static $count = 0;
$count++;
echo $count;
if($count < 3){
Test();
}
$count--;
}
Function Test1() {
//------------1 begin---------------
static $count = 0;
$count++;
echo $count; //1
if($count < 3){
//------------2 begin---------------
static $count = 0;
$count++;
echo $count; //2
if($count < 3){
//------------3 begin---------------
static $count = 0;
$count++;
echo $count; //3
if($count < 3){
echo "这里不可能执行.";
}
$count--;
//------------3 end---------------
}
$count--;
//------------2 end---------------
}
$count--;
//------------1 end---------------
}
?>
--------------------------------------递归说明----------------------------------------
1.递归函数调用其实和普通的函数调用没什么区别,只不过每次call的是同一个函数而已。
2.递归的本质。递归是一段程序的代码反复效用,把程序的参数等变量保存在一个堆栈里,直到到了边界条件以后再层层返回,将堆栈中的数据弹出计算,最后得到结果
3.递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,而且,如果递归深度太大,可能系统资源会不够用。
4.理论上,递归和循环是等价的。
所有的递归都可以转化为循环,所有的循环都可以转化为递归。
其实,求值递归的意义不大。
递归求值最终都可以用数据归纳法总结出来一个终极公式。连循环形式都不用,一个公式直接出结果。
递归和循环之间的桥接器是尾递归。
我们知道,循环 = 尾递归
所有的递归都可以转化成尾递归(即循环),区别在于转化的代价是多大,好处是多大。
递归的形式有两种,线性递归和树型递归。
线性递归就是函数只调用自己一次。树型递归则是函数调用自己多次。比如楼主的例子,就是树型递归。
不过,树型递归都是可以线性化的,毕竟,运行栈本身就是线性的(一个数组)。
这要看后面的循环步骤(或者下面层次的递归)需要多少层前面的结果。这个层数就是递归转化为循环(尾递归)的代价。比如,楼主的例子,层数就是 3。这时候,转化为循环,就是值得的。
在极端情况下,循环步骤(或者下面层次的递归)需要前面所有层的结果,这个时候,递归转化为循环,就毫无意义。
这通常是遍历的情况。比如,树结构的深度优先遍历。这时候,循环和递归没有什么区别。循环的形式还更难看,还需要自己维护一个不断伸缩的运
Function Test() {
static $count = 0; //静态变量只在首次调用时初始化,并被保持直到脚本运行结束
$count++;
echo $count;
if($count < 10){
Test();
}
$count--;//返回的时候静态变量清零
}
?>
<?php
//test() 与 test1() 等价
Function Test() {
static $count = 0;
$count++;
echo $count;
if($count < 3){
Test();
}
$count--;
}
Function Test1() {
//------------1 begin---------------
static $count = 0;
$count++;
echo $count; //1
if($count < 3){
//------------2 begin---------------
static $count = 0;
$count++;
echo $count; //2
if($count < 3){
//------------3 begin---------------
static $count = 0;
$count++;
echo $count; //3
if($count < 3){
echo "这里不可能执行.";
}
$count--;
//------------3 end---------------
}
$count--;
//------------2 end---------------
}
$count--;
//------------1 end---------------
}
?>
--------------------------------------递归说明----------------------------------------
1.递归函数调用其实和普通的函数调用没什么区别,只不过每次call的是同一个函数而已。
2.递归的本质。递归是一段程序的代码反复效用,把程序的参数等变量保存在一个堆栈里,直到到了边界条件以后再层层返回,将堆栈中的数据弹出计算,最后得到结果
3.递归需要系统堆栈,所以空间消耗要比非递归代码要大很多,而且,如果递归深度太大,可能系统资源会不够用。
4.理论上,递归和循环是等价的。
所有的递归都可以转化为循环,所有的循环都可以转化为递归。
其实,求值递归的意义不大。
递归求值最终都可以用数据归纳法总结出来一个终极公式。连循环形式都不用,一个公式直接出结果。
递归和循环之间的桥接器是尾递归。
我们知道,循环 = 尾递归
所有的递归都可以转化成尾递归(即循环),区别在于转化的代价是多大,好处是多大。
递归的形式有两种,线性递归和树型递归。
线性递归就是函数只调用自己一次。树型递归则是函数调用自己多次。比如楼主的例子,就是树型递归。
不过,树型递归都是可以线性化的,毕竟,运行栈本身就是线性的(一个数组)。
这要看后面的循环步骤(或者下面层次的递归)需要多少层前面的结果。这个层数就是递归转化为循环(尾递归)的代价。比如,楼主的例子,层数就是 3。这时候,转化为循环,就是值得的。
在极端情况下,循环步骤(或者下面层次的递归)需要前面所有层的结果,这个时候,递归转化为循环,就毫无意义。
这通常是遍历的情况。比如,树结构的深度优先遍历。这时候,循环和递归没有什么区别。循环的形式还更难看,还需要自己维护一个不断伸缩的运