关于JavaScript递归经典案例题详析

目录
  • 什么是递归,它是如何工作的?
  • 一、求和
    • (1)数字求和
    • (2)数组求和
  • 二、数据转树
  • 三、汉诺塔
  • 四、斐波那契数列
  • 总结

什么是递归,它是如何工作的?

我们先来看一下递归(recursion)的定义:

递归是一种解决问题的有效方法,在递归过程中,函数将自身作为子例程调用。

简单说程序调用自身的编程技巧叫递归。递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止。

使用递归需要避免出现死循环,为了确保递归正确工作,递归程序应该包含2个属性:

  1. 基本情况(bottom cases),基本情况用于保证程序调用及时返回,不在继续递归,保证了程序可终止。
  2. 递推关系(recurrentce relation),可将所有其他情况拆分到基本案例。

函数中自己调用自己就是递归,切记要有终止条件,不然进入死循环

一、求和

(1)数字求和

    function sum(n){
      if(n===1){
        return n=1
      }
      return n+sum(n-1)
    }
    console.log(sum(5));

执行顺序

5+sum(n-1)
5+4+sum(n-1)
5+4+3+sum(n-1)
5+4+3+2sum(n-1)
5+4+3+2+1

(2)数组求和

        function sum(arr) {
        var len = arr.length
        if (len == 0) {
          return 0
        } else if (len == 1) {
          return arr[0]
        } else {
          return arr[0] + sum(arr.slice(1))
        }
      }
      let arr = [ 1, 2, 3, 4, 5 ]
      console.log(sum(arr))

执行顺序

1+sum(2,3,4,5)
1+2+sum(3,4,5)
1+2+3(4,5)
1+2+3+4+sum(5)
1+2+3+4+5
1+2+3+9
1+2+12
1+14
15

二、数据转树

        let data = [{
                id: "01",
                pid: "",
                "name": "老王"
            },
            {
                id: "02",
                pid: "01",
                "name": "小张"
            }
        ]
  function fn(data, rootId = '') {
            const children = []      //定义一个空数组
            data.forEach(item => {
                if (item.pid === rootId) {    //如果每一项的pid=rootId就添加到数组里
                    children.push(item)
                    item.children = fn(data, item.id)
                }
            });
            return children
        }

使用递归转树 要知道根的pid是什么值才能进行下一步操作,作为起点。

执行顺序

三、汉诺塔

规则 下面三个柱子分别设为 a 、b、 c、 目标把a中的所有盘子分别从大到小依次放到c柱子中,每次只能移动一个盘子

实现思路:

  1. 将n-1个盘子从a挪到b
  2. 将n盘子从a挪到c
  3. 将n-1个盘子从b挪到c
        function fn(num, start, middle, end) {
            if(num>0){
                fn(num-1,start,end,middle)
                console.log(start+'====>'+end);
                fn(num-1,middle,start,end)
            }
           }
              fn(2,'a','b','c')

把  num作为盘子的数量  start 作为a盘子  middle作为b盘子   end作为c盘子

例如 2个盘子的执行顺序

1.第一行 把2带进去 num>0  执行第一个函数fn(2-1,start,end,middle) 又去执行了fn(1-1,start,end,middle) 发现num不大于0不仅如此if条件,回过来看 fn(2-1,start,end,middle) ,输出 console.log(a===>b)

2.第二行console.log(start+'====>'+end);   直接输出 a===>c

3.第三行 fn(2-1,middle,start,end)  执行 console.log(b===>c)  下次再去执行  fn(1-1,middle,start,end) 进入不了循环执行完毕

执行顺序有点抽象,实在不理解就按照最简单的思路去做 fn(num, start, middle, end) ,平常我们玩游戏怎么玩就去怎么做,初始图

fn(num-1,start,middle,end)  把 第二个的参数位置作为要移动的盘子 把第四个的参数位置作为移动目标    每次看图把这个公式带进去

第一步   fn(num-1,start,end,middle)   例如两个盘子 肯定是先把a-1放到b上

第二步 把盘子a放c上直接输出 console.log('a===>c')

第三步 把盘子b放c上  fn(num-1,middle,start,end,)

四、斐波那契数列

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、

        function Fibonacci(n) {
            return  n <= 1?1:Fibonacci(n - 1) + Fibonacci(n - 2)
        }

除了前两个 每次都是前一个数和前两个数的和相加等于第三个数

例如数字5举例  前一项是3  前两项是2    3+2=5

总结

到此这篇关于JavaScript递归经典案例题详析的文章就介绍到这了,更多相关JavaScript递归案例内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript递归函数定义与用法实例分析

    本文实例讲述了JavaScript递归函数定义与用法.分享给大家供大家参考,具体如下: 递归函数是一个函数通过名字调用自身的情况下形成的,比如经典的递归阶乘函数: function factorial(num) { if (num <= 1) { return 1; } else { return num * factorial(num - 1); } } 上面的这种写法,可能会造成问题: var anotherFactorial = factorial; factorial = null; c

  • JavaScript递归详述

    目录 一.什么是递归? 二.利用递归求数学题 1.求1 * 2 * 3 * 4 -*n的阶乘 2. 求斐波那契数列 三.利用递归求对应数据对象 一.什么是递归? 如果一个函数在内部可以调用其本身,那么这个函数就是递归函数.简单理解:函数内部自己调用自己, 这个函数就是递归函数. 如下所示: function fn(){ fn(); } fn(); 这个函数就是一个递归函数,当我们直接打印时,会: 发现打印错误,这是为什么呢?因为递归函数的作用和循环效果一样.当没有给他返回值的时候,它就会一直死循

  • JavaScript递归操作实例浅析

    本文实例分析了JavaScript递归操作.分享给大家供大家参考,具体如下: 问题 一个简单的递归,求n的阶乘: function factorial(n){ if (n<=1) { return 1; }else{ return factorial(n-1)*n; } } 如果像下面这样使用它,则会出错: var fcopy = factorial; factorial = null; alert(fcopy(3)); 因为fcopy指向的函数实体调用了factorial,而factorial

  • javascript递归函数定义和用法示例分析

    递归函数:是指函数直接或间接调用函数本身,则称该函数为递归函数. 这句话理解起来并不难,从概念上出发,给出以下的例子: function foo(){ console.log("函数 foo 是递归函数."); foo(); } 这个例子的 foo 函数就是一个递归函数. 当你把这个函数拿到浏览器上运行的时候,你会发现内存溢出了,为什么呢?因为这个递归函数没有停止处理或运算的出口,因此这个递归函数就演变为一个死循环. 那如何使用递归呢? 使用递归函数必须要符合两个条件: 1. 在每一次

  • 关于JavaScript递归经典案例题详析

    目录 什么是递归,它是如何工作的? 一.求和 (1)数字求和 (2)数组求和 二.数据转树 三.汉诺塔 四.斐波那契数列 总结 什么是递归,它是如何工作的? 我们先来看一下递归(recursion)的定义: 递归是一种解决问题的有效方法,在递归过程中,函数将自身作为子例程调用. 简单说程序调用自身的编程技巧叫递归.递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止. 使用递归需要避免出现死循环,

  • javascript常用经典算法实例详解

    本文实例讲述了javascript常用算法.分享给大家供大家参考,具体如下: 入门级算法-线性查找-时间复杂度O(n)--相当于算法界中的HelloWorld //线性搜索(入门HelloWorld) //A为数组,x为要搜索的值 function linearSearch(A, x) { for (var i = 0; i < A.length; i++) { if (A[i] == x) { return i; } } return -1; } 二分查找(又称折半查找) - 适用于已排好序的

  • 基于Java语言的递归运算例题详解

    目录 一.实例演示:递归求N的阶乘 二. 递归调用练习 递归求1+2+3+……10的和 顺序打印一个数字的每一位 返回一个数组成本身的数字之和 求解汉诺塔问题 求斐波那契数列第N项 递归定义:一个方法在执行过程中调用自身, 就称为 "递归". 递归的必要条件: 1. 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同. 2. 递归出口. 一.实例演示:递归求N的阶乘 public class fac { public static int factorial(int x){

  • JavaScript三大变量声明详析

    目录 前言 Var 基础写法 声明未定义值 声明定义值 不推荐写法 var 声明作用域 局部作用域 全局作用域 便捷语法 var 声明提升 Let let 作用域 冗余声明 暂时性死区 全局声明 条件声明 for 循环中的 let 常见for循环 for循环套定时器 const const 限制 for 循环中的 const 声明风格及最佳实践 总结 前言 ECMAScript 变量是松散类型的,变量可以用于保存任何类型的数据,每个变量只不过是一个用于保存任意值的命名占位符. 本文主要讲述 Ja

  • 用C语言递归实现火车调度算法详解

    目录 1.代码 2.代码详解 3.用二叉树表示调用过程 4.思维导图 笔者在李云清版的<数据结构>中第二章遇到了这道经典的火车调度题,经过对一些前辈的代码进行学习,以下将这段火车代码进行分析详解,不对之处,还请各位大佬指示,不胜感激! 1.代码 题目如下: 2.8编号为1,2,3,4的四列火车通过一个栈式的列车调度站,可能得到的调度结果有哪些?如果有n列火车通过调度站,请设计一个算法,输出所有可能的调度结果. 算法运用的思想是运用栈+递归,算法的难点也在于此.先上代码: #include &l

  • JavaScript函数调用经典实例代码

    目录 JavaScript函数调用经典例题 JS函数的定义与调用方法 总结 JavaScript函数调用经典例题 1.输入框判断是不是闰年 2.随机数判断是不是闰年 3.输入框判断是不是质数 4.随机数判断是不是质数 5.封装函数,判断日期是否合法 思考:首先我们采用函数调用的方法,将需要调用的函数都写在 js 文件夹里面,调用的时候会更方便.需要注意的是不要忘记在html中引入js. html代码: <body> <span>是否为闰年</span> <inpu

  • 例题详解Java dfs与记忆化搜索和分治递归算法的使用

    目录 一.dfs(深度优先搜索) 1.图的dfs 2.树的dfs 二.记忆化搜索 1.普通递归:O(2^n) 2.记忆化搜索: O(n) 三.分治 四.算法题 1.dia和威严 示例 2.小红点点点 示例1 3.kotori和素因子 示例1 示例2 4.kotori和糖果 示例 一.dfs(深度优先搜索) 1.图的dfs /** * 深度优先搜索 * * @param node * @param set */ public void DFS(Node node, Set<Node> set)

  • Java几个重要的关键字详析

    目录 1.extends 2.implements 3.final 4.native 5.static 6.transient 7.synchronized 9.this 10.super 10.1.子类对象实例化的过程 11.访问修饰符 1.extends 用于类继承类,用法:class+子类名+extends+父类名+{} class Animal{}//父类 class cat extends Animal{}//子类用extends实现继承 注意:一个类只能用extends关键字声明继承

  • React报错map() is not a function详析

    目录 总览 Array.isArray Array.from Object.keys 总览 当我们对一个不是数组的值调用map()方法时,就会产生"TypeError: map is not a function"错误.为了解决该错误,请将你调用map()方法的值记录在console.log上,并确保只对有效的数组调用map. 这里有个示例来展示错误是如何发生的. const App = () => { const obj = {}; // ️ Uncaught TypeErro

  • Vue组件间的通信方式详析

    目录 前言 组件之间通信的场景 父子组件之间的通信 父组件通过 prop 向子组件传递数据 子组件通过自定义事件向父组件传递数据 兄弟组件之间的通信 状态提升 隔代组件之间的通信 attrs/attrs/listeners provide/inject 基于 $parent/$children 实现的 dispatch 和 broadcast 前言 在Vue组件库开发过程中,Vue组件之间的通信一直是一个重要的话题,虽然官方推出的 Vuex 状态管理方案可以很好的解决组件之间的通信问题,但是在组

随机推荐