递归

函数调用其本身

#include <stdio.h>
void up_and_down(int);

int main() {
    up_and_down(1);
    return 0;
}

void up_and_down(int n) {
    printf("Level %d: n location %p\n", n, &n); // 1
    if (n < 4)
        up_and_down(n + 1);
    printf("LEVEL %d: n location %p\n", n, &n); // 2
}

递归的基本原理:

①每一级的函数调用都有自己的变量。

第1级调用中的 n 不同于第2级调用中的n,因此程序创建了4个独立的变量,虽然每个变量的名字都是n,但它们分别具有不同的值。当程序最终返回到对 up_and_down() 的第1级调用时,原来的n仍具有其初始值 1。

②每一次函数调用都会有一次返回。

当程序流执行到某一级递归的结尾处时,它会转移到前一级递归继续执行。程序不能直接返回到 main() 中的初始调用部分,二十通过递归的每一级逐步返回,即从 up_and_down() 的某一级递归返回到调用它的上一级。

③递归函数中,位于递归调用前的语句和各级被调函数具有相同的执行顺序。

④递归函数中,位于递归调用后的语句的执行顺序和各个被调函数的顺序相反。

⑤虽然每一级递归都有自己的变量,但是函数代码并不会得到复制。

函数代码是一系列的计算机指令,而函数调用就是从头执行这个指令集的一条命令。一个递归调用会使程序从头执行相应函数的指令集。除了为每次调用创建变量,递归调用非常类似于一个循环语句。

⑥递归函数中必须包含可以终止递归调用的语句。

通常情况下,递归函数会使用一个 if 条件语句或其他类似的语句以便当函数参数达到某个特定值时结束递归调用。

 

尾递归

把递归调用语句放在函数结尾 即恰在 return 语句之前。因为出现在函数尾部,作用相当于一条循环语句,所以是最简单的递归形式。

factor.c

long rfact(int n) {
    long ans;
    if (n > 0)
        ans = n * rfact(n - 1);
    else
        ans = 1;
    return ans;
}

调用 fact() 时,fact(n) = n*fact(n-1)。就可以通过调用 fact(n-1) 来计算 fact(n),递归必须在某个地方结束,可以在 n 为0时把返回值设为1,从而达到结束递归的目的。

递归处理反序

编写一个函数将一个整数转换成二进制形式。数值以2为底进行表示。

奇数的最后一位一定是 1,偶数的最后一位一定是 0,所以通过计算 5%2 得出 5 的二进制形式中最后一位数字是 1 或 0。

对于数值 n,其二进制数的最后一位是 n%2,因此计算出的第一个数字就是需要输出的最后一位数字。这就需要使用一个递归函数来实现。在函数中,首先在递归调用之前计算 n%2的数值,然后在递归调用语句之后进行输出。这样,计算出的第一个数值反而在最后一个输出。

为了得出下一个数字,需要把原数值除以 2。这种计算就相当于在十进制下把小数点左移一位。如果此时得出的数值是偶数,则下一个二进制位的数值是0;若得出的数值是奇数,则下一个二进制位的数值就是1.

 

递归剑法

——摘抄自晴神

1.调用自己就是调用别人

2.描述清楚一层做的事情

3.不要陷入到层层展开中


 

怎么解题

拿到一道题目,先分析问题可能满足什么样的性质,然后猜想可能会使用什么样的算法去解决这个问题,接着在假设使用某个算法的情况下,试图去推导整个过程,在这个过程当中可能会碰到猜想的算法解不出来的情况,那就只能继续看问题有什么样的性质,然后再去做另外的算法猜想,这样一直下去直到解决。在这个期间可能会碰到一些情况,比如说对问题的分析不太够,总是想不到正确的算法,就会一直卡着。也有可能是偶然想到了正确的算法,但是没有把算法正确的套到问题上,这也会让你一直卡着,都是因为做的题目太少了!也没有试过去总结,所以再碰到相似的题目性质的时候,没有办法一眼就辨认出来和已经做过的题目的一些联系,或者是把算法套到题目上的时候不够熟练,解决方法无非是多做题多总结,或者也可以看别人的总结,比如说书博客之类的。但是,最终都是要落实到自己也参与到实际的思考和编码当中才能更好的理解,不然在碰到新的题目的时候仍然是一脸懵逼。可以在跟完别人的总结,并且自己做题之后,可以去尝试一下总结一些自己的想法,这样才能把东西都变成自己的东西。

怎么解决一个分治的问题?

能分:数字,特别是整数,所以在设计问题表述的时候一定要去先找数字,如果题目要求的问题当中本身就带有数字,那正好直接把问题的本身拿来当作函数的定义就可以了。如果没有的话,就看一下题目描述里面有没有数字,有的话就考虑一下能不能够作为问题表述当中的一部分。也有一种可能就是题目本身没有涉及到数字,那我们就可以去想办法创造出数字,比如说题目球的始序列或者字符串的某个性质,就可以把序列或者字符串的长度用来作为问题表述的数字

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值