浅谈尾递归和goto循环
2015-08-11 09:45
323 查看
在学习python递归的时候接触到尾递归,尾递归的要求是,函数的最后一个运算是递归调用,而不是其他的运算。
举阶乘为例子
第一个函数是我们熟知的递归函数,它的优点是简介易懂。缺点也十分经典,就是大量耗费栈空间,每次调用递归时都要把上一次的数据压栈。第二个函数是我们的尾递归函数。比较两个函数,在递归调用部分,递归函数的最后一个运算是乘法,而尾递归函数里的递归调用是最后一个运算。当最后一个运算是乘法这一类的运算时,我们的就一定要压栈保留原来的数据,用于后来的运算。但是尾递归就不用了,对于尾递归来说,上一次函数的任务已经完成了。它的数据已经通过参数传递了,是完全没有保留意义的,我们是完全可以不用压栈的。
由此,其实在部分语言中,会有我们所称的尾递归优化。编译器会为尾递归提供编译级别的优化,比如至始至终递归函数都只是用一个栈,不会出现栈溢出的情况。但是,可惜的是,我们的python、java还有c++其实是没有尾递归优化的。当然,如果真的在这些语言中需要尾递归优化,其实是可以通过异常处理的修改来实现的。这里提供一个网址:http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html
当然,上述的方法其实是牵强而为之。
今天还了解到一个叫goto 的语句,十分高级,但是也十分危险。
在程序中,mark是printf语句的标识符,使用goto语句可以使程序直接执行到mark行,起到一个无条件跳转的功能。但是因为是无脑跳转,所以在跳转完以后可能会出现变元没申明的语法错误。如上面的程序,x的声明就被跳过,在后期使用x时就会出现错误。goto语句一直是被认为是有反编程设计思想的。但是,尽管很难把握,goto语句在跳出循环方面还是有很大的作用,尤其是多重嵌套。
举阶乘为例子
// tail_recursion.cpp int fact(int num ){ if(num <= 0 ) return 0 ; else if(num == 1 ) return 1 ; else if (num > 1 ) { return num * fact(num - 1 ) ; } } int fact_tail(int num , int ans){ if(num == 1 ){ return ans ; } else if(num <= 0 ){ return 0 ; } else if(num > 1 ){ return fact_tail(num - 1 , ans * num ) ; } }
第一个函数是我们熟知的递归函数,它的优点是简介易懂。缺点也十分经典,就是大量耗费栈空间,每次调用递归时都要把上一次的数据压栈。第二个函数是我们的尾递归函数。比较两个函数,在递归调用部分,递归函数的最后一个运算是乘法,而尾递归函数里的递归调用是最后一个运算。当最后一个运算是乘法这一类的运算时,我们的就一定要压栈保留原来的数据,用于后来的运算。但是尾递归就不用了,对于尾递归来说,上一次函数的任务已经完成了。它的数据已经通过参数传递了,是完全没有保留意义的,我们是完全可以不用压栈的。
由此,其实在部分语言中,会有我们所称的尾递归优化。编译器会为尾递归提供编译级别的优化,比如至始至终递归函数都只是用一个栈,不会出现栈溢出的情况。但是,可惜的是,我们的python、java还有c++其实是没有尾递归优化的。当然,如果真的在这些语言中需要尾递归优化,其实是可以通过异常处理的修改来实现的。这里提供一个网址:http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html
当然,上述的方法其实是牵强而为之。
今天还了解到一个叫goto 的语句,十分高级,但是也十分危险。
// goto.cpp int main (){ goto mark ; int x = 1 ; mark : printf("*") ; return 0 ; }
在程序中,mark是printf语句的标识符,使用goto语句可以使程序直接执行到mark行,起到一个无条件跳转的功能。但是因为是无脑跳转,所以在跳转完以后可能会出现变元没申明的语法错误。如上面的程序,x的声明就被跳过,在后期使用x时就会出现错误。goto语句一直是被认为是有反编程设计思想的。但是,尽管很难把握,goto语句在跳出循环方面还是有很大的作用,尤其是多重嵌套。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 那些年,我还在学习C# 学习笔记续
- Ruby 魔法 学习笔记之一
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- sqlserver 数据库学习笔记
- C#中的递归APS和CPS模式详解
- WinForm实现按名称递归查找控件的方法
- CSS学习笔记Padding 属性中参数的定义与使用
- prototype 1.5 & scriptaculous 1.6.1 学习笔记
- prototype 学习笔记整理
- Oracle学习笔记(六)
- C++联合体转换成C#结构的实现方法
- C#中的尾递归与Continuation详解
- 关于SQLServer2005的学习笔记 XML的处理