递归与尾递归的区别与应用

一、递归

1.在定义一个过程或函数时,出现调用自己的成分,称为递归
2.递归一般运行时效率都很低,耗时很长;
3.可以将复杂的问题很容易的表示出来,比如汉诺塔的问题,能很好地展现递归的作用;
4.递归在实际问题中都需要一个出口,不能无限进行下去。

二、尾递归

1.如果一个函数中所有递归形式的调用都出现在函数的末尾,则称这个递归函数是尾递归
2.递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分;
3.尾递归只需要保留最后一个函数堆栈,不需要保存很多中间函数的堆栈

特点:在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。

代码示例:

递归:

double Fact(int n) {
     if (n == 1) {
         return 1;
     }
     return n * Fact(n - 1);
}

若n=5,执行次序如下:
Fact(5);
5* Fact(4);
5* (4* Fact(3));
5* (4* (3* Fact(2)));
5* (4* (3* (2* Fact(1))));
5* (4* (3* (2* 1)));
120

可见这种方法空间复杂度为O(n),无论是时间上还是空间上的消耗都很大,极易出现爆栈的情况,进而出现了尾递归的应用

尾递归:

double Fact(int n, double total) {
     if (n == 1) {
         return total;
     }
     return Fact(n - 1, n * total);
}

若n=5,执行次序如下:
Fact(5,1);
Fact(4,5);
Fact(3,20);
Fact(2,60);
Fact(1,120);
120

由于尾递归只需要保留最后一个函数堆栈,不需要保存很多中间函数的堆栈,所以空间复杂度为O(1),因此大大提高了执行效率

尾递归的应用在时间上没有太大的变化,但空间上的优化很大,有效的避免了爆栈现象,是解题过程中的一种很好的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值