尾递归的三个经典案例<阶乘><斐波那契数列><汉诺塔数列>[C语言]

 递推公式等号右侧有几个f(n),就要多用几个参数

比如f(n) = f(n-1)+f(n-2)就是多用两个,f(n) = n*(f(n-1))就是多用一个

#include <stdio.h>
#include <stdlib.h>
int recur_fact(int n,int fn){
    /*factorial
        n! is f(n) = n*(f(n-1))
        f(0) = 0;
        f(1) = 1;
        f(2) = 2*f(1) = 2;
        f(3) = 3*f(2) = 6;
    */
    if (n <1){
        return -1;
    }else if (n == 1){
        return fn;
    }else{
        return recur_fact(n-1,n*fn);/*n*fn是下一层的结果,这个fn数学上写作f(n-1)*/
    }
}
int recur_fibo(int n,int fn1, int fn2){
    /*fibonacci
        f(n) = f(n-1)+f(n-2);
        f(0) = 0;
        f(1) = 1;               f1
        f(2) = f(1)+f(0) = 1;   f1
        f(3) = f(2)+f(1) = 2;   f1+f2
        f(4) = f(3)+f(2) = 3;   f(3)+f1
        f(5) = f(4)+f(3) = 5;   f(4)+f(3)
    */
    if (n <0){
        return -1;
    }else if (n == 0){
        return 0;
    }else if (n == 1 || n == 2){/*前两个条件的输出值要固定,终止条件为n==2*/
        return fn2;
    }else {        
        return recur_fibo(n-1,fn2,fn1+fn2);/*这里第三个参数的fn1+fn2就是下一层的结果,第二个参数的f2是本层的结果*/
        /*这里第三个参数的fn1和fn2数学上写作f(n-1)和f(n-2),他们的和就是f(n)*/
        /*第二个参数的fn2实际上就是为了接收变化后的f(n),他的递归最小单位是n=2返回1*/
    }
}
int main(){
    printf("factorial:");
    for (int i=1;i<11;i++)
        printf("%d ",recur_fact(i,1));
    printf("\n");   
 
    printf("fibonacci:");
    for (int i=1;i<11;i++)
        printf("%d ",recur_fibo(i,1,1));
    printf("\n"); 
    return 0;
}

输出结果: 

factorial:1 2 6 24 120 720 5040 40320 362880 3628800 
fibonacci:1 1 2 3 5 8 13 21 34 55 

=================================分割线=================================== 

/*the tower of Hanoi problem*/
#include <stdio.h>
#include <stdlib.h>
unsigned long long hanoi(int n, unsigned long long fn){
    /*
        f(n) = 2*f(n-1) + 1
        f(1) = 1;
        f(2) = 3;
        f(3) = 7;
        f(4) = 15;
    */
   if (n <0){
       return -1;
   }else if (n == 0){
       return 0;
   }else if (n == 1){
       return fn;
   }else {
       return hanoi(n-1, 2*fn+1); 
   }
}
int main(){    
    for (int i=1;i<65;i++)
        printf("%llu ", hanoi(i, 1));
    return 0;
}

输出:

1 3 7 15 31 63 127 255 511 1023 2047 4095 8191 16383 32767 65535 131071 262143 524287 1048575 2097151 4194303 8388607 16777215 33554431 67108863 134217727 268435455 536870911 107334217727 268435455 536870911 1073741823 2147483647 4294967295 8589934591 17179869183 34359738367 68719476735 137438953471 274877906943 549755813888046511103 8796093022207 175921867 1099511627775 2199023255551 4398046511103 8796093022207 17592186044415 35184372088831 70368744177663 140737488355327 281474976710655 56294995342740991 18014398509481983 360287971311 1125899906842623 2251799813685247 4503599627370495 9007199254740991 18014398509481983 36028797018963967 72057594037927935 144115188075855871 223372036854775807 18446744073709
288230376151711743 576460752303423487 1152921504606846975 2305843009213693951 4611686018427387903 9223372036854775807 18446744073709551615 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值