手机版

C#递归函数的详细介绍和用法

时间:2021-10-06 来源:互联网 编辑:宝哥软件园 浏览:

什么是递归函数/方法?任何方法都可以调用其他方法或自身,当这个方法调用自身时,我们称之为递归函数或递归方法。一般来说,递归有两个特点:1。递归方法将一直调用自己,直到满足某些条件;2.递归方法会有一些参数,它会传递一些新的参数值给自己。什么是递归函数?函数和方法没有本质区别,只是函数只在类内部使用。过去C#中只有方法,但匿名函数始于。NET 3.5。因此,我们最好称之为递归方法,而不是递归函数,本文称之为递归。为什么在应用程序中使用递归?什么时候用递归?怎么用?写任何程序都可以用赋值和if-then-else语句来表示,而while语句可以用赋值、if-then-else和递归来表示(《数据结构基础(C语言版)》-c中数据结构基础来自Ellis Horowitz)递归解决方案对于复杂的开发来说是非常方便和强大的,但是频繁使用调用栈可能会导致性能问题(有时性能极差)。我们来看看下面这张图:Proj0

调用堆栈图我打算介绍一些例子来帮助您更好地理解递归的风险和回报。1.阶乘阶乘(!)是小于某个数的所有正整数的乘积。0!=1 1!=1 2!=2 * 1!=2 3!=3 * 2!=6 .n!=n * (n - 1)!以下是计算阶乘(无递归)的实现方法:复制代码如下:公共长阶乘(int n) {if (n==0)返回1;长值=1;for(int I=n;I 0;I-){ value *=I;}返回值;}下面是计算阶乘的递归方法,比前面的代码更简洁。复制的代码代码如下:公共长阶乘(int n){ if(n==0)//限制条件,方法调用本身受限返回1;返回n *阶乘(n-1);}如您所知,n的阶乘实际上是n-1乘以n的阶乘,而n0。它可以表示为阶乘(n)=阶乘(n-1) * n这是方法的返回值,但是我们需要一个条件,如果n=0,它将返回1。这个程序的逻辑现在应该很清楚了,这样我们就很容易理解了。2.斐波那契数列斐波那契数列是按以下顺序排列的数字:0,1,1,2,3,5,8,13,21,34,55,如果F0=0,F1=1,那么Fn=Fn-1 Fn-2使用以下方法计算Fn(无递归,性能良好)。复制的代码如下。long[]f=new long[n ^ 1];f[0]=0;f[1]=1;for(int I=2;I=n;I){ f[I]=f[I-1]f[I-2];}返回f[n];}如果我们使用递归方法,这段代码会更简单,但它的性能很差。复制代码如下:公共长fib(int n){ if(n==0 | | n==1)//满足返回n的条件;返回光纤(k - 2)光纤(k-1);} strong span style=' font-size : medium ' 3。布尔组合/SPAN/STRONG有时我们需要解决的问题比斐波那契序列复杂得多,例如,我们需要枚举布尔变量的所有组合。换句话说,如果n=3,那么我们必须输出以下结果:真、真、真、假、真、假、假、真、假、真、假、假、假、假、真、假、假、真、假、假、假。如果n很大,不递归很难解决这个问题。复制代码如下: public void composition booms(字符串结果,int counter){ if(counter==0)return;bool[] booleans=new bool[2] { true,false };for(int j=0;J2;j){ StringBuilder StringBuilder=new StringBuilder(结果);stringBuilder。追加(字符串。格式(“{0}”),布尔值[j]。ToString()))。ToString();if(计数器==1)控制台。WriteLine(stringBuilder。ToString());复合工具(stringBuilder。ToString(),计数器-1);}}现在我们调用上面的方法:复制代码如下: Composition Boolean(字符串。空,3);Ian Shlasko建议我们使用递归如下:复制代码如下: public void布尔组合(int count){布尔组合(count-1,' true ');booleanctions(count-1,“false”);} private void booleanctions(int计数器,string partialOutput) { if(计数器=0) Console。WriteLine(partialOutput);else { booleanctions(counter-1,partialOutput ',true ');BooleanCompositions(计数器- 1,partialOutput ',false ');}} 4.Get innerException如果想得到内部异常,那么选择递归方法,非常有用。复制代码如下:公共异常getinnerexception(exception onex){ return(ex。innerexception==null)?ex : Getinerexception(ex。InnerException);}为什么要获取最后一个innerException?这不是本文的主题。我们的主题是,如果你想得到最里面的innerException,你可以通过递归方法来实现。

这里的代码:复制代码如下:return(例如。innerexception==null)?ex : Getinerexception(ex。InnerException);相当于下面的代码,复制代码如下:if (ex。inner exception==null)//约束retunex返回GetInnerException(例如。InnerException);//用innerException作为参数调用自己。现在,一旦我们得到一个异常,我们就可以找到最里面的内部异常。示例:复制代码如下:try {抛出新异常('这是异常'),new exception('这是第一个内部异常。newexception('这是最后一个内部异常。)));} catch(异常ex) { Console。WriteLine(Getinerexception(ex))。消息);}我曾经想写一篇关于匿名递归的文章,但是发现我的解释无法超越那篇文章。5.搜索文档Proj1

我在演示项目中使用了递归,供您下载。通过这个项目,可以搜索某个路径,得到当前文件夹及其子文件夹中所有文件的路径。复制代码如下:私有字典字符串,字符串错误=新字典字符串,字符串();private Liststring结果=new Liststring();private void SearchForFiles(字符串路径){ try { foreach(目录中的字符串文件名。GetFiles(path))//获取当前路径{ result }中的所有文件。添加(FIlename);} foreach(目录中的字符串目录。getdirectory(路径))//获取当前路径{ SearchForFiles(目录)中的所有文件夹;//方法用一个新参数调用自己,这里!} }捕捉(系统。异常(例如){错误。添加(路径,例如。消息);//将错误消息存储在一个字典中,路径在key}}看来这个方法不需要满足任何条件,因为如果每个目录中没有子目录,它会自动遍历所有子文件。综上所述,我们其实可以用递归算法代替递归,性能会更好,但是可能需要更多的时间开销和非递归函数。但关键是一定要根据场景选择最佳的实施模式。詹姆斯麦卡弗里博士认为,除非真的没有办法,否则不应该尽可能多地使用递归。你可以看看他的文章。我认为:a)如果性能非常重要,请避免使用递归;b)如果递归不是很复杂,请避免使用递归;c)如果a和b不满意,请毫不犹豫地使用递归。例如:第1节(阶乘):这里使用递归并不复杂,所以避免使用递归。第二节(斐波那契):不建议这样递归。当然,我不是想贬低递归的价值。记得人工智能的一个重要章节有一个Minimax算法,都是递归实现的。但是如果您决定使用队列规划方法,您最好尝试使用存储来优化它。版权声明:本文由作者曲托尼原创。未经作者同意,本声明必须保留,原文链接应在文章页面的明显位置给出,否则视为侵权。

版权声明:C#递归函数的详细介绍和用法是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。