算法之递归算法,从认识递归到掌握递归

一、递归概述

1.在了解本文之前需要准备什么知识

在了解递归之前,需要掌握数据结构中的栈数据结构,因为递归调用和栈的原理息息相关,如果你还不会栈的话,可以观看我的栈入门基础,附上链接: 栈基础入门

2.递归的基本介绍

1)递归的概念

简单来说,递归就是方法【函数】自身调用自身,每一次调用的时候传入的参数都是不一样的,或者换一种说法,递归就是方法【函数】不断进行压栈的过程。

2)如何理解递归

递归顾名思义,我们可以将其分为两部分去理解:

  1. 递出去
    什么叫做递出去呢?因为方法的递归调用其实就是进行压栈【push】操作,方法每执行自己一次,都会压栈一次,直到最终达到递归结束的条件,此时就不会在进行压栈了,就要开始“归回来了”。
  2. 归回来
    归回来就是递出去的时候达到了结束递归的条件,此时处于栈顶的方法会逐渐弹出【pop】,栈顶每结束【弹出】一个方法,就会返回到上一个调用它的方法,这个方法弹栈的过程就是“归回来”。

3.递归在内存中的模型

我们以java虚拟机(简称JVM)为例,讲解递出去与归回来的内存模型:在JVM中,有一个区域叫做栈区,所有方法(包括main方法)的执行都是在栈区中单独开辟一个独属于该方法的栈空间,整个方法在栈区中进行压栈操作,我们以如下代码为例画图讲解。

public class no_01_递归的概念 {
    public static void main(String[] args) {
        //调用方法m,传入一个3
        m(3);
    }
    public static void m(int n){
        //递归结束的条件:参数n等于0时方法结束
        if (n == 0)
            return;
        //递归调用,参数应该逐渐向递归结束的条件靠近
        m(n - 1);
    }
}

在这里插入图片描述

4.递归需要注意的事项

1)每一个方法执行的时候都会在栈区开辟一块独属于该方法的栈帧(栈空间),然后这块独立空间在栈区进行压栈操作,main方法是第一个被执行的方法,所以main方法总是第一个压栈。
2)当一个方法执行完毕后,或者遇到return,该方法就会结束,遵循谁调用,就将结果返回给谁的原则。
3)如果方法中的参数是引用数据类型的变量【比如数组】,那么递归调用的时候,所有方法共享同一个对象。
4)递归的时候必须要有结束递归的条件,这一点非常重要!!!否则会出现死递归,也就是递出去就回不来了,此时会发生栈溢出错误。
5)递归的时候必须向结束递归的条件靠近,否则也会发生栈溢出。
6)因为栈区空间是有限的,所以即使在向递归结束的条件靠近,也有可能出现栈溢出,因为递归太深了。

二.递归的基本使用

1.递归打印数字

1)题目介绍

1.题目:给你一个数字n = 5,并将n打印出来,n逐渐递减1,当n == 3时,结束打印。
2.要求:使用递归
3.结果: 5 4

2)思路分析

1.递归结束的条件为:n == 3
2.将当前的n输出
3.调用递归:递归时每一次传入的参数要减1
在这里插入图片描述

3)代码实现

public class 递归打印 {
    public static void main(String[] args) {
        print(5);
    }
    public static void print(int n){
        //递归结束的条件
        if (n == 3)
            return;
        //打印当前的n
        System.out.println("n = " + n);
        //递归调用,参数递减1
        print(n - 1);
    }
}

2.递归求阶乘

1)题目介绍

1.题目:使用递归求解n的阶乘(n >= 0)
2.要求:使用递归求解

2)思路分析

1.首先判断传入参数n是否为0或者是1,如果是直接返回n即可
2.递归结束的条件应该为:当n逐渐递减为1的时候,结束递归(此步骤可以和上一步重合,因为上一步也是判断n是否为1,为1就直接返回n)
3.让当前的n与下一次自身调用的返回值累乘
在这里插入图片描述

3)代码实现

public class 递归阶乘 {
    public static void main(String[] args) {
        int result = getFactorial(4);
        System.out.println(result);
    }
    public static int getFactorial(int n){ //4
        //1.判断n的值是否为0或1,如果是直接返回n
        if (n == 1 || n == 0)
            return n;
        else//2.递归调用,让当前的n与下一次调用的返回值相乘
            return n * getFactorial(n - 1);
    }
}

三、递归小结

1.理清楚递出去【方法压栈】,与归回来【方法弹栈】的含义。
2.知道方法结束后返回的位置是在上一级调用该方法的地方。
3.找准递归结束的条件,避免死递归【一直压栈,没有返回,栈溢出】
4.递归的应用途径非常广泛,比如
1)迷宫问题
2)八皇后问题
3)归并排序算法
4)快速排序算法
5)二分查找算法
6)分支算法
等等许多经典的算法与面试题都会用到递归,所以掌握好递归算法是非常有必要性的!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ocean&21

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值