递归和分治思想2
让编程改变世界
Change the world by program
递归定义
在高级语言中,函数自己调用和调用其他函数并没有本质的不同。 我们把一个直接调用自己或通过一系列的调用语句间接地调用自己的函数,称作递归函数。 不过,写递归程序最怕的就是陷入永不结束的无穷递归中。切记,每个递归定义必须至少有一个条件,当满足这个条件时递归不再进行,即函数不再调用自身而是返回值。 比如之前我们的Fbi函数结束条件是:i < 2。 对比了两种实现斐波那契的代码,迭代和递归的区别是:迭代使用的是循环结构,递归使用的是选择结构。 使用递归能使程序的结构更清晰、更简洁、更容易让人理解,从而减少读懂代码的时间。 但大量的递归调用会建立函数的副本,会消耗大量的时间和内存,而迭代则不需要此种付出。 递归函数分为调用和回退阶段,递归的回退顺序是它调用顺序的逆序。 举个例子,计算n的阶乘n! [caption id="attachment_2215" align="alignnone" width="391"] n的阶乘[/caption] 这样我们就不难设计出递归算法: [codesyntax lang="c"]int factorial( n ) { if( 0 == n ) return 1; else return n * factorial( n - 1 ); }[/codesyntax] 假设我们n的值传入是5,那么:
实例分析
题目要求:编写一个递归函数,实现将输入的任意长度的字符串反向输出的功能。 例如输入字符串FishC,则输出字符串ChsiF。 应用递归的思想有时可以很轻松地实现一些看似不太容易实现的功能,例如这道题。 要将一个字符串反向地输出,童鞋们一般采用的方法是将该字符串存放到一个数组中,然后将数组元素反向的输出即可。 这道题要求输入是任意长度,所以不用递归的话,实现起来会比较麻烦(当然你可以用之前我们讲过的动态申请内存那招)。 我们说过,递归它需要有一个结束的条件,那么我们可以将“#”作为一个输入结束的条件。 [codesyntax lang="c"]void print() { char a; scanf(“%c”, &a); if( a !=‘#’) print(); if( a !=‘#’) printf(“%c”, a); }[/codesyntax] 假设我们从屏幕上输入字符串:ABC#