博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
尾递归优化
阅读量:5884 次
发布时间:2019-06-19

本文共 1194 字,大约阅读时间需要 3 分钟。

hot3.png

关于循环优化的理论比较复杂,我们现在暂时切换到一些简单些的优化吧
我们经常在写代码时会使用递归调用,我们知道递归调用通常代价比较大,
但是递归调用比较符合我们的思考方式,写代码比较容易。
其实实际上对于一种比较特殊的递归调用,编译器可以直接帮助我们做优化,
将递归调用直接优化为非递归调用,这一类递归调用在编译器里面称为尾递归调用
(Tail Recursive Call).
比如函数
  1. int primes(int a, int b){
  2.     if(a==0)return b==1;
  3.     if(b==0)return a==1;
  4.     return primes(b,a%b);
  5. }
复制代码
像上面的一个代码,只有在代码的最后一行调用函数自身的代码称为尾递归,大部分现代
的编译器都能够对上面的代码进行优化,将递归优化成一个循环,因为其做法只需要修改所有
函数输入值,然后跳到函数入口就可以了。
有些尾递归调用可能不是很容易看出来,比如
  1. int primes(int a, int b){
  2.     if(a==0)return b==1;
  3.     if(b==0)return a==1;
  4.     if(a<b){
  5.         return primes(a,b%a);
  6.     }else{
  7.         return primes(a%b,b);
  8.     }
  9. }
复制代码
虽然上面代码有两次递归调用,但是两次都是尾递归,它们分别在两个不同分支的最后面。
此外另外一种比较常见的尾递归调用形式是:
  1.    double honic(int n){
  2.         if(n==1)return 1.0;
  3.         else return 1.0/n+honic(n-1);
  4.    }
复制代码
这里,递归调用在一个表达式中间,虽然它是最后一次计算(+操作)的一个参数,但是由于加法
满足结合率,我们可以改变所有累加的顺序,所以上面的编译器也可以自动转化为循环。
同样,计算
  1.    double honic(int n){
  2.         if(n==1)return 1.0;
  3.         else return honic(n-1)+1.0/(n*n);
  4.    }
复制代码
编译器也可以自动优化,(虽然后面还有计算1.0/(n*n),但是编译器可以自动优化,加法满足交换率).
像下面代码
  1.    double Fib(int n){
  2.         if(n<=1)return 1.0;
  3.         else return Fib(n-1)+Fib(n-2);
  4.    }
复制代码
这个代码中,两次递归调用中,只有后面那次调用(Fib(n-2))可以转化为循环的一部分,但是前面那次递归调用无法转化。
所以对这样的代码,最好还是通过手工优化。(其实,这里的函数Fib不含有任何指针之类会引起歧异的代码,从理论上,
编译也应该能够优化掉,但是实际上现在通常的编译器不会做这样的优化)

转载于:https://my.oschina.net/u/218425/blog/51949

你可能感兴趣的文章
360浏览器内核控制标签meta说明
查看>>
android AsyncTask
查看>>
poj 3225 【线段树】
查看>>
序列化
查看>>
Linux 查询命令
查看>>
Some tips for your Number 157842 369 the earth number
查看>>
梦网云通讯API接口匹配状态报告规则
查看>>
Linux之线程管理
查看>>
Cocos2d-x游戏《雷电大战》开源啦!要源代码要资源快快来~~
查看>>
常见随机变量的数学期望和方差
查看>>
eclipse黄色警告(finally block does not complete normally) ,不建议在finally中使用return语句...
查看>>
msyql sql语句收集
查看>>
面试题一份
查看>>
关于ubuntu上执行错误命令报错
查看>>
使用grep恢复被删文件内容
查看>>
【转】Google 的眼光
查看>>
在同一台电脑上使用两个github账户
查看>>
简单一招,使解决方案下的项目版本号统一
查看>>
js 发布订阅模式
查看>>
Word Ladder(LintCode)
查看>>