Java 初探 递归

9 篇文章 0 订阅

递归原理

函数调用栈实例:主函数 main() 调用 funcA() , funcA() 调用 funcB() , funcB() 再自我调用(递
归)

在这里插入图片描述

函数调用栈的基本单位是帧(frame)。每次函数调用时,都会相应地创建一帧, 记录该函数实例在二
进制程序中的返回地址(return address),以及局部变量、传入参数等, 并将该帧压入调用栈。若在
该函数返回之前又发生新的调用,则同样地要将与新函数对应的一帧压入栈中,成为新的栈顶。函数一
旦运行完毕,对应的帧随即弹出,运行控制权将被交还给该函 数的上层调用函数,并按照该帧中记录的
返回地址确定在二进制程序中继续执行的位置。
在任一时刻,调用栈中的各帧,依次对应于那些尚未返回的调用实例,亦即当时的活跃函数实例
(active function instance)。特别地,位于栈底的那帧必然对应于入口主函数main(), 若它从调用栈
中弹出,则意味着整个程序的运行结束,此后控制权将交还给操作系统。
此外,调用栈中各帧还需存放其它内容。比如,因各帧规模不一,它们还需记录前一帧的起始地址,以
保证其出栈之后前一帧能正确地恢复。
作为函数调用的特殊形式,递归也可借助上述调用栈得以实现。比如在上图中,对应于 funcB() 的自
我调用,也会新压入一帧。可见,同一函数可能同时拥有多个实例,并在调用栈中 各自占有一帧。这些
帧的结构完全相同,但其中同名的参数或变量,都是独立的副本。比如在 funcB() 的两个实例中,入
口参数 m 和内部变量 i 各有一个副本。

编写递归函数分析

分析:

什么样的问题, 能够写成递归函数?
1、下一步计算需要用到上一步结果
2、答案由多个值构成, 值之间的选择具有相关性
3、如何结束递归
4、如何传递递归(下一层递归)

例子一

递归求阶乘

计算阶乘(factorial)

n ! = { 1 n = 0 n ∗ ( n − 1 ) ! n > 0 n!=\begin{cases} 1 & n=0 \\ n*(n-1)! & n>0 \end{cases} n!={1n(n1)!n=0n>0

code

/***
 * 递归求阶乘
 */
public class A {

    public static void main(String[] args) {
        System.out.println(jie(3));
    }

    public static int jie(int n) {
        if (n == 0) return 1;
        else return n * jie(n - 1);
    }
}

例子二

计算斐波那契数列

Fibonacci sequence:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ……
f ( n ) = { 0 n = 0 1 n = 1 f ( n − 2 ) + f ( n − 1 ) n > 1 f(n)=\begin{cases} 0 & n=0 \\ 1 & n=1 \\ f(n-2)+f(n-1) & n>1 \end{cases} f(n)=01f(n2)+f(n1)n=0n=1n>1

/**
 * 计算 斐波那契数列
 **/
public class B {

    public static void main(String[] args) {

        System.out.println(shulie(3));
    }

    public static int shulie(int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;
        else  return shulie(n-1)+shulie(n-2);
    }
}

例子三

计算最大公约数(辗转相除法)

gcd(12, 32) = 4

gcd(a,   b)
gcd(32,  12)
gcd(12,  8)
gcd(8,   4)
gcd(4,   0)

g c d ( a , b ) = { a b = 0 g c d ( b , a % b ) b ≠ 0 gcd(a,b)=\begin{cases} a & b=0 \\ gcd(b,a \% b) & b\neq 0 \end{cases} gcd(a,b)={agcd(b,a%b)b=0b=0

public class C {

    public static void main(String[] args) {
        System.out.println(gcd(32,12));

    }

    public static int gcd(int a, int b) {
        if (b == 0) return a;
        else return gcd(b, a % b);
    }
}

小结

上述递归例子十分明确都包含了递归结束的条件以及传递下一层(递归公式)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值