递归的一些问题(斐波那契数列,遍历Dom树,遍历子元素以及其对应的ID名与类名)(遍历子元素下面所有的文本)

本文介绍了递归的基本概念,探讨了递归的思想精髓,并详细解释了编写递归程序的三个关键要素。此外,还提供了几个JavaScript实现的具体示例,如斐波那契数列计算、DOM树遍历等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:首先介绍什么是递归:
递归就是在函数的内部调用自己的函数的形式。
二:递归的思想精髓:
正如上面所描述的场景,递归就是有去(递去)有回(归来),如下图所示。“有去”是指:递归问题必须可以分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决,就像上面例子中的钥匙可以打开后面所有门上的锁一样;“有回”是指 : 这些问题的演化过程是一个从大到小,由近及远的过程,并且会有一个明确的终点(临界点),一旦到达了这个临界点,就不用再往更小、更远的地方走下去。最后,从这个临界点开始,原路返回到原点,原问题解决。
这里写图片描述 
更直接地说,递归的基本思想就是把规模大的问题转化为规模小的相似的子问题来解决。特别地,在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况,这也正是递归的定义所在。格外重要的是,这个解决问题的函数必须有明确的结束条件,否则就会导致无限递归的情况。

三:递归的三要素
   在我们了解了递归的基本思想及其数学模型之后,我们如何才能写出一个漂亮的递归程序呢?笔者认为主要是把握好如下三个方面:

1、明确递归终止条件;
2、给出递归终止时的处理办法;
3、提取重复的逻辑,缩小问题规模。

1). 明确递归终止条件
   我们知道,递归就是有去有回,既然这样,那么必然应该有一个明确的临界点,程序一旦到达了这个临界点,就不用继续往下递去而是开始实实在在的归来。换句话说,该临界点就是一种简单情境,可以防止无限递归。
2). 给出递归终止时的处理办法
   我们刚刚说到,在递归的临界点存在一种简单情境,在这种简单情境下,我们应该直接给出问题的解决方案。一般地,在这种情境下,问题的解决方案是直观的、容易的。
3). 提取重复的逻辑,缩小问题规模*
   我们在阐述递归思想内涵时谈到,递归问题必须可以分解为若干个规模较小、与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决。从程序实现的角度而言,我们需要抽象出一个干净利落的重复的逻辑,以便使用相同的方式解决子问题。

四。具体实例:
1.斐波那契数列的JS代码实现:

 //----------------------------我是分割线-----------------------------------------
    //性能优化的问题
    var obj = {};
    function  FibonacciSequence ( n ) {
        if(obj[n]) { //如果进入说明这个位已经求过了
            return obj[n];
        }else if(n == 1 || n ==2) {
            //将这个数据也存入对象中
            obj[n] = 1;
            return 1;
        }else {
            //将这个数据也存入对象中
            obj[n] = FibonacciSequence(n-1) + FibonacciSequence(n-2);
            return obj[n];
        }
    }
    //函数的调用
    console.log ( FibonacciSequence ( 50 ) );

2.遍历元素的子元素以及遍历Dom树的实现代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="father">
    <div></div>
    <div></div>
    <div>
        <p></p>
        <p>
            <b></b>
            <b></b>
        </p>
    </div>
</div>
<script>

    var father = document.getElementById('father')
    //遍历dom树的函数
    /**
     * 作用:遍历元素内部所有的子元素
     * @param ele
     */
    //定义一个数组来存放遍历出来的元素
    var list = [];
    function getDomElements ( ele ) {
        var childlist = ele.children;
        //这里面的递归终止条件隐含是:当元素没有子元素的话,那么childlist.length是0,循环自动执行结束
        for(var i = 0;i<childlist.length;i++){
            //获取子元素,并将子元素取出来放入数组中
            var child = childlist[i];
            list.push(child);
            //获取子元素的子元素
            getDomElements(child);
        }
    }
    //遍历id为father的Div里面的所有的子元素
    getDomElements(father);
    console.log ( list );

    //遍历整个dom树的操作
    getDomElements(document);
    console.log ( list );

</script>
</body>
</html>

3.遍历元素的子元素以及其对应的ID名与类名的实现代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="father">
    <div id="div1" class="div1"></div>
    <div id="div2" class="div2"></div>
    <div id="div3" class="div3">
        <p></p>
        <p id="p" class="p">
            <b></b>
            <b id="b" class="b"></b>
        </p>
    </div>
</div>
<script>

    var father = document.getElementById('father')
    //遍历dom树的函数
    /**
     * 作用:遍历元素内部所有的子元素以及子元素的ID名及类名
     * @param ele
     */
    //定义一个数组来存放遍历出来的元素以及类名以及ID名
    var list = [];
    function getDomElements ( ele ) {
        var childlist = ele.children;
        //这里面的递归终止条件隐含是:当元素没有子元素的话,那么childlist.length是0,循环自动执行结束
        for(var i = 0;i<childlist.length;i++){
            //获取子元素,并将子元素取出来放入数组中
            var child = childlist[i];
            var childName = childlist[i].className;
            var childID = childlist[i].id;
            list.push(child,childName,childID);
            //获取子元素的子元素
            getDomElements(child);
        }
    }
    //遍历id为father的Div里面的所有的子元素以及类名以及ID名
    getDomElements(father);
    console.log ( list );

</script>
</body>
</html>

3.1 对应的遍历结果
这里写图片描述

4.遍历元素的子元素以及对应的文本实现代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="father">
    我是fatherdiv
    <div id="div1" class="div1">我是第一个div</div>
    <div id="div2" class="div2">我是第二个div</div>
    <div id="div3" class="div3">
        我是第三个div
        <p>我是第一个p标签</p>
        <p id="p" class="p">
            我是第二个p标签
            <b>我是第一个b标签</b>
            <b id="b" class="b">我是第二个b标签</b>
        </p>
    </div>
</div>
<script>

    var father = document.getElementById('father')
    //遍历dom树的函数
    /**
     * 作用:遍历元素内部所有的子元素以及子元素的文本内容
     * @param ele
     */
    //定义一个数组来存放遍历出来的元素以及类名以及ID名
    var list = [];
    function getDomElements ( ele ) {
        //获取子元素数组
        var eleChild = ele.childNodes;
        for(var i=0;i<eleChild.length;i++) {
            //拿到具体的子元素
            var child = eleChild[i];
            //找到子元素的文本
            var childtxt = child.innerText;

            list.push(childtxt);
            getDomElements(child);
        }
    }
    //遍历id为father的Div里面的所有的子元素以及类名以及ID名
    getDomElements(father);
    console.log ( list );

</script>
</body>
</html>

这里写图片描述

其中的undefined是因为代码之间有回车的问题,只需要将所有的代码都写成一行,那么就可以去掉undefined了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值