C语言递归

C语言函数可以自我调用。如果函数内部一个语句调用了函数自己,则称这个函数是“递归”。递归是以自身定义的过程。也可称为“循环定义”。
递归的例子很多。例如定义整数的递归方法是用数字1,2,3,4,5,6,7,8,9加上或减去一个整数。例如,数字15是7+8;数字21是9+12;数字12是9+3。
一种可递归的计算机语言,它的函数能够自己调用自己。一个简单的例子就是计算整数阶乘的函数factor()数N的阶乘是1到N之间所有数字的乘积。例如3的阶乘是1×2×3,即是6。
factor()和其等效函数fact()如例4-10所示。

非递归函数fact()的执行应该是易于理解的。它应用一个从1开始到指定数值结束的循环。
在循环中,用“变化”的乘积依次去乘每个数。
factor()的递归执行比fact()稍复杂。当用参数1调用factor()时,函数返回1;除此之外的其它值调用将返回factor(n-1)*n这个乘积。为了求出这个表达式的值,用(n-1)调用factor()一直到n等于1,调用开始返回。
计算2的阶乘时对factor()的首次调用引起了以参数1对factor()的第二次调用。这次调用返回1,然后被2乘(n的初始值),答案是2(把printf()语句插入到factor()中,察看各级调用及其中间答案,是很有趣的)。
当函数调用自己时,在栈中为新的局部变量和参数分配内存,函数的代码用这些变量和参数重新运行。递归调用并不是把函数代码重新复制一遍,仅仅参数是新的。当每次递归调用返回时,老的局部变量和参数就从栈中消除,从函数内此次函数调用点重新启动运行。可递归的函数被说成是对自身的“推入和拉出”。
大部分递归例程没有明显地减少代码规模和节省内存空间。另外,大部分例程的递归形式比非递归形式运行速度要慢一些。这是因为附加的函数调用增加了时间开销(在许多情况下,速度的差别不太明显)。对函数的多次递归调用可能造成堆栈的溢出。不过溢出的可能性不大,因为函数的参数和局部变量是存放在堆栈中的。每次新的调用就会产生一些变量的复制品。这个堆栈冲掉其它数据和程序的存储区域的可能性是存在的。但是除非递归程序运行失控,否则不必为上述情况担心。
递归函数的主要优点是可以把算法写的比使用非递归函数时更清晰更简洁,而且某些问题,特别是与人工智能有关的问题,更适宜用递归方法。递归的另一个优点是,递归函数不会受到怀疑,较非递归函数而言,某些人更相信递归函数。编写递归函数时,必须在函数的某些地方使用if语句,强迫函数在未执行递归调用前返回。如果不这样做,在调用函数后,它永远不会返回。在递归函数中不使用if语句,是一个很常见的错误。在开发过程中广泛使用printf()和getchar()可以看到执行过程,并且可以在发现错误后停止运行。

 

 


1. 递归就是: 函数自己调用自己
--------------------------------------------------------------------------------
 
这是一个最简单的递归, 不过它会一直执行, 可用 Ctrl+C 终止.
--------------------------------------------------------------------------------
 
#include <stdio.h>

void prn(void) {
    printf("C++Builder 2009/n");
    prn();  /* 自调用; 注意它会一直执行, 可用 Ctrl+C 终止执行 */
}

int main(void)
{
    prn();
    getchar();
    return 0;
}
--------------------------------------------------------------------------------

2. 使用递归一定要有跳出的条件:
--------------------------------------------------------------------------------
 
#include <stdio.h>

void prn(int num) {
    printf("%d/n", num);
    if (num > 0) prn(--num); 
}

int main(void)
{
    prn(9);
    getchar();
    return 0;
}
--------------------------------------------------------------------------------

3. 实例: 翻转字符串
--------------------------------------------------------------------------------
 
#include <stdio.h>

void revers(char *cs);

int main(void)
{
    revers("123456789");

    getchar();   
    return 0;
}

void revers(char *cs)
{
    if (*cs)
    {
        revers(cs + 1);
        putchar(*cs);
    }
}
--------------------------------------------------------------------------------

4. 实例: 阶乘
--------------------------------------------------------------------------------
 
#include <stdio.h>

int factorial(int num);

int main(void)
{
    int i;
    for (i = 1; i <= 9; i++)
    printf("%d: %d/n", i, factorial(i));

    getchar();   
    return 0;
}

int factorial(int num)
{
    if (num == 1)
        return(1);
    else
        return(num * factorial(num-1));
}
--------------------------------------------------------------------------------

5. 实例: 整数到二进制
--------------------------------------------------------------------------------
 
#include <stdio.h>

void IntToBinary(unsigned num);

int main(void)
{
    IntToBinary(255); /* 11111111 */
    getchar();
    return 0;
}

void IntToBinary(unsigned num) {
    int i = num % 2;
    if (num > 1) IntToBinary(num / 2);
    putchar(i ? '1' : '0');
//    putchar('0' + i);  /* 可代替上面一句 */
}
--------------------------------------------------------------------------------

6. 剖析递归:
--------------------------------------------------------------------------------
 
#include <stdio.h>

void prn(unsigned n);

int main(void)
{
    prn(1);
    getchar();
    return 0;
}

void prn(unsigned n) {
    printf("%d: %p/n", n, &n);  /* A */
    if (n < 4)
        prn(n+1);               /* B */
    printf("%d: %p/n", n, &n);  /* C */
}
--------------------------------------------------------------------------------


本例输出效果图:



分析:
程序运行到 A, 输出了第一行.
此时 n=1, 满足 < 4 的条件, 继续执行 B 开始了自调用(接着会输出第二行); 注意 n=1 时语句 C 还有待执行.
...如此循环, 一直到 n=4, A 可以执行, 但因不满足条件 B 执行不了了; 终于在 n=4 时得以执行 C.
但此时内存中有四个函数都等待返回(分别是 n=1、2、3、4 时), 咱们分别叫它 f1、f2、f3、f4.
f4 执行 C 输出了第五行, 函数返回, 返回给 f3(此时 n=3), f3 得以继续执行 C, 输出了第六行.
f3 -> f2 -> 继续 C, 输出了第七行.
f2 -> f1 -> 继续 C, 输出了第八行, 执行完毕!

如此看来, 递归函数还是很费内存的(有时不如直接使用循环), 但的确很巧妙.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值