精华内容
下载资源
问答
  • java 递归程序实现

    千次阅读 2018-11-11 20:14:15
    java 递归程序实现 本文我们介绍编程语言的一个核心概念————递归。介绍递归功能特性,以及如何使用递归解决不能类型问题。 1. 理解递归 1.1. 递归定义 java中函数调用机制支持方法可以调用自身,这种功能...

    java 递归程序实现

    本文我们介绍编程语言的一个核心概念————递归。介绍递归功能特性,以及如何使用递归解决不能类型问题。

    1. 理解递归

    1.1. 递归定义

    java中函数调用机制支持方法可以调用自身,这种功能称为递归。举例,我们计算求和函数:

    public int sum(int n) {
        if (n >= 1) {
            return sum(n - 1) + n;
        }
        return n;
    }
    

    递归函数有两个主要前提:

    • 终止条件——当一定条件满足时,函数返回特定值,不再递归调用
    • 递归调用——函数调用自身,其输入值更接近终止条件

    每次递归调用都会在jvm栈内存空间中增加栈帧,因此我们不注意递归深度,可能会发生栈内存溢出错误。 我们可以利用尾递归优化进行规避。

    1.2. 尾递归VS头递归

    当递归调用是执行函数的最后部分则称为尾递归,反之为头递归。我们现在通过尾递归方式实现上面的示例:

    public int tailSum(int currentSum, int n) {
        if (n <= 1) {
            return currentSum + n;
        }
        return tailSum(currentSum + n, n - 1);
    }
    

    使用尾递归,递归调用是执行方法中最后需要执行的内容,在当前方法中不再有其他内容需要去执行。因此,理论上无需存储当前函数的栈帧。所以编译器能利用这点优化内存,但java编译器暂时没有针对尾递归进行优化。

    1.3. 递归VS迭代

    递归可以帮助简化解决负责问题,且代码更简洁、可读。但通常需要更多的栈内存以及增加每次递归调用。作为替代方案,能使用递归解决的问题,也可以使用迭代方式实现。下面通过迭代方式实现上面求和的示例:

    public int iterativeSum(int n) {
        int sum = 0;
        if(n < 0) {
            return -1;
        }
        for(int i=0; i<=n; i++) {
            sum += i;
        }
        return sum;
    }
    

    相比于递归,迭代方法性能更好。但迭代更复杂,相比于递归更难理解。例如:遍历二叉树时两种方法对比很明显。

    在头递归、尾递归以及迭代方法中选择最佳方案,取决于特定问题和情况。

    2. 示例实战

    下面我们通过示例使用递归解决几个问题。

    2.1. 求10的n次方

    假如我们需要求10 的n次方。输入为n。通过递归方式实现。首先技术10 的 (n-1)次方,然后乘以10。然后计算10 的 (n-1)次方,即为10 的 (n-2)次方乘以10,以此类推,直到计算(n-n)次方,值为1。java实现代码如下:

    public int powerOf10(int n) {
        if (n == 0) {
            return 1;
        }
        return powerOf10(n-1) * 10;
    }
    

    2.2. 求斐波那契数列的第n个元素值

    从0和1开始,斐波那契数列中每个元素是前两个元素之和:0,1,1,2,3,5,8,13,21,34……
    所以,给定数值n,我们的问题是求第n个元素。使用递归方案,我们需要考虑终止条件以及递归调用。
    还好,两种都非常简单。求n个元素值,只要先求f(n) = f(n-1) + f(n-2) (递归调用)。同时 f(0) = 0 和 f(1) = 1 (终止条件)。那么定义递归方法就比较简单:

    public int fibonacci(int n) {
        if (n <= 1) {
            return n;
        }
        return fibonacci(n-1) + fibonacci(n-2);
    }
    

    2.3 十进制转二进制

    下面我们通过递归方法实现十进制转二进制问题。需求是输入十进制数n,输出二进制字符串。
    方法为十进制数除以2,记录余数继续用商除以2。一直除直到商为0.然后使用倒叙写出所有余数,就获得结果。
    因此,我们的问题是写一个方法按照相反的顺序返回这些余数:

    public String toBinary(int n) {
        if (n <= 1 ) {
            return String.valueOf(n);
        }
        return toBinary(n / 2) + String.valueOf(n % 2);
    }
    

    2.4 计算二叉树高度

    二叉树高度定义为从根到最深叶子节点的边数。我们的问题是计算给定二叉树的高度值。
    一个简单方法是查找最深的叶子,然后计算其到根的边数。使用递归的方案实现,我们重新描述二叉树高度定义————求二叉树中左分支和右分支中最大的高度,然后加一。如果根没有左分支和右分支,其高度为0.

    代码实现为:

    public int calculateTreeHeight(BinaryNode root){
        if (root!= null) {
            if (root.getLeft() != null || root.getRight() != null) {
                return 1 + 
                  max(calculateTreeHeight(root.left), 
                    calculateTreeHeight(root.right));
            }
        }
        return 0;
    }
    

    通过示例,我们看到通过递归方式解决一些问题非常简单。

    3. 总结

    本文我们介绍了java中递归的概念,并演示了几个简单示例。

    展开全文
  • 我们发现中都是一些条件只有满足这些条件了才...课前准备 云课堂APP 班级二维码 前情回顾 方法的嵌套调用 1方法嵌套调用的写法 2方法嵌套程序的流程执行 教学目标的确定 通过汉诺塔小游戏程序了解java递归的编程思想和
  • Java递归算法

    2020-12-22 17:40:01
    Java递归算法是基于Java语言实现的递归算法。  递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。递归算法对解决一大类问题很有效,它可以使算法简洁和易于理解。  ...
  • 在本篇文章里小编给大家带来了关于Java递归求和1+2+3+...+n实例内容,需要的朋友们可以学习参考下。
  • 绍关于Java程序多线程递归弥补管理漏洞
  • java 递归详解

    2021-02-12 21:52:13
    在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解.递归的分类:递归分为两种,直接递归和间接递归。直接递归称为方法自身调用自己。间接递归可以A方法调用B方法,B...

    递归算法是一种直接或间接地调用自身的算法。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解.

    递归的分类:

    递归分为两种,直接递归和间接递归。

    直接递归称为方法自身调用自己。

    间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。

    for循环实现99乘法表

    public class test99 {

    public static void main( String[] args ) {

    for (int i=1;i<=9;i++){

    for (int j=1;j<=i;j++){

    System.out.print(j+" * "+i+ " = "+(i*j) +" ");

    }

    }

    }

    }

    递归实现99乘法表

    public class diguidemo {

    public static void main( String[] args ) {

    digui(9);

    }

    private static void digui( int i ) {

    if (i==1){

    System.out.println("1*1=1");

    }else {

    digui(i-1);

    for (int j=1;j<=1;j++){

    System.out.print(j + "*" + i + "=" + j * i + " ");

    }

    }

    }

    }

    471f5228e1cb43c2bbb3d726e1d9e3ac.png

    递归求和

    public class diguiqiuhe {

    public static void main( String[] args ) {

    int num=5;

    int sum=getSum(num);

    System.out.println(sum);

    }

    private static int getSum( int num ) {

    if (num==1){

    return 1;

    }

    return num+getSum(num-1);

    }

    }

    bca4b4fe0330f57d04e88e62ac5e1e30.png

    展开全文
  • java递归算法(一)——详解以及几个经典示例

    万次阅读 多人点赞 2018-12-06 00:12:12
    递归就是一个程序或函数在其中定义或说明有之间或者间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可以描述出解题过程所需要的多...

    什么是递归

    递归就是一个程序或函数在其中定义或说明有之间或者间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可以描述出解题过程所需要的多次重复计算,大大的减少了程序的代码量,递归的能力在于用有限的语句来定义对象的无限集合,一般来说,递归需要边界条件,递归前进段和递归返回段,当边界条件不满足时,递归前进,当边界条件满足时,递归返回。

    递归示例

    我这里采用的是一个很常见的问题,也是我在知乎上面看到的

    • 假设你在一个电影院,你想知道自己坐在哪一排,但是前面人很多,你懒得去数了,于是你问前一排的人「你坐在哪一排?」,这样前面的人 (代号 A) 回答你以后,你就知道自己在哪一排了——只要把 A 的答案加一,就是自己所在的排了,不料 A 比你还懒,他也不想数,于是他也问他前面的人 B「你坐在哪一排?」,这样 A 可以用和你一模一样的步骤知道自己所在的排。然后 B 也如法炮制,直到他们这一串人问到了最前面的一排(或者说问到了知道自己是哪一排的人,预示着调用结束),第一排的人告诉问问题的人「我在第一排」,最后大家就都知道自己在哪一排了

    递归算法实例

    • 阶乘
      要求给一个数值,计算它的阶乘,例如给的是4 阶乘为432*1
    public class DiGui {
    
        public static int getFactorial(int n) {
            if (n >= 0) {
                if (n == 0) {
                    System.out.println(n + "!=1");
                    return 1;
                } else {
                    System.out.println(n);
                    int temp = n * getFactorial(n - 1);
                    System.out.println(n + "!=" + temp);
                    return temp;
                }
            }
            return -1;
        }
    
        public static void main(String[] args) {
            getFactorial(4);
        }
    
    }
    

    输出
    在这里插入图片描述
    由下面的图形可以知道详细的过程

    在这里插入图片描述
    getFactorial方法在调用自身的时候,它的参数是4,每次减一,这个方法返回自身,知道减到0,于是方法返回,这样会引发一系列的返回,脱离被放弃的那一层,每当返回时,这个方法把调用它的单数n与其调用的下一层的返回值想乘,注意,在最底层返回之前,实际上是在同一时刻有四个不同的getFactorial方法实例存在,最外层是4,最里面的是1

    递归的二分查找

    首先二维数组一定是有序的,
    在有序的数组array[]中,不断地将中间值(mid)和被查找的值比较,如果被查找的值等于affay[],就返回下标array[mid],否则就像查找的范围缩小一半,如果被查找的小于array【mid】,就继续查找左边得值,如果查找大于array【mid】就向右边查找,直到查找为空,查找结束!
    在这里插入图片描述详细代码请查看我的这一篇博客
    https://blog.csdn.net/qq_40688338/article/details/84557959

    分治算法

    当我们求解某些问题,由于这些问题要处理的数据相当多,或求解的方式比较复杂,使得直接求解在时间上相当长,或者直接无法求出,对于这类问题,我们往往把它分成几个子问题,找到求出这个子问题的解法后,再找到合适问题的解法,如果这些子问题还较大,难以解决,我们可以把它再分成介个更小的子问题,以此类推,直到找到解法为止,这就是分治解法的基本思想。
    上面所说的递归的二分查找就是一个分治算法的经典例子,分治算法常常是一个方法,在这个方法中含有两个对自身的递归调用,分别对应于问题的两个部分,
    二分查找中,将查找范围分成比查找值大的一部分和比查找值较小的一部分,每次递归只有一部分执行。

    汉诺塔问题

    汉诺塔问题是由很多放置在三个塔座上的盘子组成的一个古老的难题,如下图所示,所有的盘子的直径是不同的。并且盘子中央都有一个洞使得它刚好可以放在塔座上,所有的盘子刚开始都是在a座上,这个难题的目标是将左右的盘子都从塔座a,移到塔座c上,每次只可以移动一个盘子,并且任何一个盘子都不可以放置在比它小的盘子上,
    在这里插入图片描述这个问题可以先从简单的方面想,然后一步一步出发,假设有2个盘子,盘子的大小我按照阿拉伯数字命名。从小到大,如果a上面有两个盘子,分别是1,2那么我们只需要把1的盘子移到b上面,然后把2的盘子移到c上面,最后把b上面的盘子1移动到c上面就可以了,这样两个盘子的问题就解决了,
    如果是三个盘子呢?我们一样的来命名1,2,3,假设先把1的盘子移动到c的上面,然后把2的盘子移动到b上面,这样目前就是a上面的是3,b上面的是2,c上面的是1,然后将c上面的盘子移动到b上面,继续把a的盘子移动到c上面,这样的话,目前就是b上面有1,2,c上面的有3,现在答案已经很清楚了,将b上面的盘子移动到a上面,然后第二个盘子移动到c上面,最后a的盘子移动到c上面,这样问题就解决了,
    但是如果有四个,五个,n个盘子呢?这个时候递归的思想就很好的解决这样的问题了,当只有两个盘子的时候,我们只需要将b塔座作为中介,将盘子1放到中介b上面,然后将盘子2放到c上面,最后将b上面的盘子1移动到c盘就可以了

    所以无论多少盘子,我们都将其看做只有两个盘子,假设n个盘子在a的上面,我们将其看做只有两个盘子,只有(n-1)和n这两个盘子,

    • 先将a上面的n-1的哪一个盘子放到塔座b上面,然后将第n的盘子放到目标塔上面,
    • 然后a的上面为空,看做中间塔,b上面的有n-1个盘子,将第n-2以下的盘子看成一个盘子,放到中间a塔上面,然后将第n-1的盘子放到c上面,
    • 这是发现a上面有n-2个盘子,b上面为空,按照上面的方式以此类推,直到全部放到冰箱里面

    简单的来说

    1. 从初始塔a上移动到包含n-1个盘子到c上面
    2. 将a上面剩下的一个盘子,放到c上面
    3. 然后假设b上面有n-1个盘子,然后将它看成为n继续将看成n的盘子中间的n-1个盘子放到a上面
    4. 将b上面剩下的那个盘子放到c上面。
     public static void main(String[] args) {
    //        getFactorial(4);
            move(4,"A","B","C");
        }
    
        /**
         * 汉诺塔问题
         *
         * @param dish 盘子个数(也表示名称)
         * @param from 初始塔座
         * @param temp 中介塔座
         * @param to   目标塔座
         */
        public static void move(int dish, String from, String temp, String to) {
          if (dish == 1) {//圆盘只有一个的时候 将其从a移动到c
                System.out.println("将盘子" + dish + "从塔座" + from + "移动到目标塔座" + to);
            }else {
                move(dish-1,from,to,temp);//a为初始塔座,b为目标塔座,c为中介塔座
                System.out.println("将盘子"+dish+"从塔座"+from+"移动到目标"+to);//把a上面的最下面的一个盘子移到c上面
                move(dish-1,temp,from,to);//b为初始塔座,c为目标塔座,a为中介塔座
            }
        }
    

    输出
    在这里插入图片描述

    归并排序

    归并排序算法的中心是归并两个已经有序的数组,归并两个有序的数组a和b,就生成了第三个有序的数组c,数组就是包含数组a和数组b的所有数据项,同时该算法采用经典的分治策略

    在这里插入图片描述
    未使用递归算法

        public static void main(String[] args) {
    //        getFactorial(4);
    //        move(4,"A","B","C");
            int[] array = {11, 22, 33, 44, 55, 66, 77, 88, 99, 100, 104};
            int[] arrayB = {1, 21, 41, 51, 61, 71, 81, 91};
            int[] arrayC = new int[19];
            merge(array,arrayB,arrayC);
            display(arrayC);
        }
    
        /**
         * @param arrayA 数组a
         * @param arrayB 数组B
         * @param arrayC 数组C
         */
        public static void merge(int[] arrayA,
                                 int[] arrayB,
                                 int[] arrayC) {
            int a = 0;
            int b = 0;
            int c = 0;
            while (a < arrayA.length && b < arrayB.length) {//当a和b都有数据数才执行
                if (arrayA[a] < arrayB[b]) {//当a的数小于b的数时
                    arrayC[c++] = arrayA[a++];//将a的数添加到c中并且下标加1
                } else {
                    arrayC[c++] = arrayB[b++];//将b中的数添加到c中并且下标加一
                }
            }
            //走到这一步的时候要么是a中没有数或者是b中没有数
            while (a < arrayA.length) {
                arrayC[c++] = arrayA[a++];//如果A中存在则将剩下的数添加到c中
            }
            while (b < arrayB.length) {
                arrayC[c++] = arrayA[b++];//如果b中的数存在则先加到c中
            }
    
        }
    
        /**
         * 排序
         */
    
        public static void display(int[] array) {
            for (int j = 0; j < array.length; j++) {
                System.out.print(array[j] + ",");
    
            }
        }
    

    输出
    在这里插入图片描述
    详细的步骤我在代码上面已经写下来了

    递归排序
    • 先将数组分成两半
    • 再把每一半分成两个1/4,
    • 继续把1/4分解成1/8依次类推
    • 直到分割成一个一个的数组,再把这些数据归并到一起直到有序
      在这里插入图片描述
    public static void main(String[] args) {
    
            int[] arr = {12, 41, 2, 3, 6, 54, 15, 21, 41, 85, 94, 12, 46};
            arr = merSort(arr, 0, arr.length - 1);
            System.out.println(Arrays.toString(arr));
        }
    
        public static int[] merSort(int[] arr, int start, int last) {
            if (last > start) {
                //也可以是(start+last)/2,这样写是为了防止数组长度很大造成两者相加超过int范围,导致溢出
                int mid = start + (last - start) / 2;
                merSort(arr, start, mid);//左边数组的排序
                merSort(arr, last, mid);//右边数组的排序
                merge(arr, start, mid, last);
            }
            return arr;
        }
    
        public static void merge(int[] arr, int start, int mid, int last) {
            int[] temp = new int[last - start + 1];//临时定义的数组
    
            int i = start;//定义左边数组的下标
            int j = mid + 1;//定义右边数组的下标
            int k = 0;
            while (i <= mid && j <= last) {
                if (arr[i] < arr[j]) {
                    temp[k++] = arr[i++];
                } else {
                    temp[k++] = arr[j++];
                }
    
            }
            //            把左边的数移动到新的数组
            while (i <= mid) {
                temp[k++] = arr[i++];
            }
    //        把右边的数移动到新的数组中
            while (j <= last) {
                temp[k++] = arr[j++];
            }
    //        把新数组中的数覆盖到arr中
            for (int a = 0; a < temp.length; a++) {
                arr[a + start] = temp[a];
            }
        }
    

    输出在这里插入图片描述

    归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(NlogN)。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(NlogN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。

    展开全文
  • 规则1:每次只能移动一个圆盘 规则2:任何时候都不允许将较大的圆盘压在较小的圆盘上 规则3:在满足移动规则1和2的前提下,可将圆盘移动到A,B,C中任一塔座上 ...本程序java语言编写,递归方式实现的演示程序
  • java 快速排序 递归The function calls itself until someone stops it. 该函数将自行调用,直到有人停止它为止。 Recursion can feel difficult to new developers. Perhaps that's because many resources teach...

    java 快速排序 递归

    The function calls itself until someone stops it.

    该函数将自行调用,直到有人停止它为止。

    Recursion can feel difficult to new developers. Perhaps that's because many resources teach it using algorithmic examples (Fibonacci, linked-lists). This piece will hopefully introduce things plainly, using one simple example.

    对于新开发人员而言,递归可能会感到困难。 也许是因为许多资源都使用算法示例(斐波纳契(Fibonacci),链接列表)来教它。 希望通过一个简单的例子,这篇文章将简单地介绍一下。

    核心思想 (Core Idea)

    Recursion is when a function calls itself until someone stops it. If no one stops it then it'll recurse (call itself) forever.

    递归是指函数调用自身直到有人停止它。 如果没有人停止,它将永远递归 (自称)。

    no-this-is-patrick

    Recursive functions let you perform a unit of work multiple times. This is exactly what for/while loops let us accomplish! Sometimes, however, recursive solutions are a more elegant approach to solving a problem.

    递归函数使您可以多次执行一个工作单元。 这正是for/while循环让我们完成的! 但是,有时递归解决方案是解决问题的一种更优雅的方法。

    倒数功能 (Countdown Function)

    Let's create a function that counts down from a given number. We'll use it like this.

    让我们创建一个从给定数字开始倒数的函数。 我们将像这样使用它。

    countDownFrom(5);
    // 5
    // 4
    // 3
    // 2
    // 1

    And here's our algorithm to solve this problem.

    这是我们解决此问题的算法。

    1. Take one parameter called number. This is our starting point.

      取一个称为number参数。 这是我们的出发点。

    2. Go from number down to 0, logging each one along the way.

      number降低到0 ,并沿途记录每个number

    We'll start with a for loop approach and then compare it to a recursive one.

    我们将从for循环方法开始,然后将其与递归方法进行比较。

    命令式方法(循环) (Imperative approach (loops))

    function countDownFrom(number) {
    	for (let i = number; i > 0; i--) {
    		console.log(i);
    	}	
    }
    
    countDownFrom(5);
    // 5
    // 4
    // 3
    // 2
    // 1

    This one contains both algorithmic steps.

    这包含两个算法步骤。

    1. ✅ Take one parameter called number.

      ✅取一个称为number参数。

    2. ✅ Log everything from number to 0.

      ✅记录从number0所有内容。

    递归方法 (Recursive approach)

    function countDownFrom(number) {
    	if (number === 0) {
    		return;
    	}
    
        console.log(number);    
        countDownFrom(number - 1);
    }
    
    countDownFrom(5);
    // 5
    // 4
    // 3
    // 2
    // 1

    This one also passes.

    这也过去了。

    1. ✅ Take one parameter called number.

      ✅取一个称为number参数。

    2. ✅ Log everything from number to 0.

      ✅记录从number0所有内容。

    So conceptually the two approaches are the same. However, they get the job done in different ways.

    因此,从概念上讲,这两种方法是相同的。 但是,他们以不同的方式完成工作。

    调试我们的命令性解决方案 (Debugging our imperative solution)

    For a more visual example, let's put a debugger in our loop version and throw it into Chrome Developer Tools.

    对于更直观的示例,让我们在循环版本中放入debugger ,然后将其放入Chrome开发者工具中。

    function countDownFrom(number) {
    	for (let i = number; i > 0; i--) {
    		console.log(i);
    		debugger;
    	}	
    }

    countdownFrom-iterative

    See how it uses an extra variable, i, to track the current number? As you iterate i decreases, eventually hitting 0 and terminating.

    看看它如何使用额外的变量i来跟踪当前数字吗? 随着您的迭代, i逐渐减少,最终达到0并终止。

    And in the for loop we specified "stop if i > 0".

    for循环中,我们指定“如果i > 0停止”。

    调试我们的递归解决方案 (Debugging our recursive solution)

    function countDownFrom(number) {
    	if (number === 0) {
    		return;
    	}
    
        console.log(number);
    	
    	debugger;
    
        countDownFrom(number - 1);
    }

    countdownFrom-recursive

    The recursive version doesn't need extra variables to track its progress. Notice how the pile of functions (call stack) grows as we recurse?

    递归版本不需要额外的变量来跟踪其进度。 注意我们递归时函数堆( 调用堆栈 )如何增长?

    That's because each call to countDownFrom adds to the stack, feeding it number - 1. By doing this we're we're passing along an updated number each time. No extra state needed!

    这是因为对countDownFrom的每次调用countDownFrom添加到堆栈中,并向其提供number - 1 。 通过这样做,我们每次都传递一个更新的number 。 不需要额外的状态!

    That's main difference between the two approaches.

    这是两种方法之间的主要区别。

    1. Iterative uses internal state (extra variables for counting, etc).

      迭代使用内部状态(用于计数的其他变量等)。
    2. Recursive does not, it simply passes updated parameters between each call.

      递归没有,它只是在每次调用之间传递更新的参数。

    But how does either version know when to stop?

    但是,哪个版本知道何时停止?

    无限循环 (Infinite Loops)

    In your travels, you may have been warned about the dreaded infinite loop.

    在旅行中,您可能已经被警告过可怕的无限循环。

    🚨 THIS RUNS FOREVER, BE WARNED 🚨
    while (true) { console.log('WHY DID YOU RUN THIS?!' }
    
    🚨 THIS RUNS FOREVER, BE WARNED 🚨
    for (i = 0;;) { console.log('WHY DID YOU RUN THIS?!') }

    Since they'd theoretically run forever, an infinite loop will halt your program and possibly crash your browser. You can prevent them by always coding a stopping condition.

    由于理论上它们将永远运行,因此无限循环将暂停您的程序,并可能导致浏览器崩溃。 您可以通过始终编写停止条件来防止它们发生。

    ✅ This does not run forever
    x = 0;
    while (x < 3) { console.log(x); x++; }
    
    ✅ This does not run forever
    for (x = 0; x < 3; x++) { console.log(x); }

    In both cases we log x, increment it, and stop when it becomes 3. Our countDownFrom function had similar logic.

    在这两种情况下,我们都记录x ,递增x ,然后在x变为3时停止。 我们的countDownFrom函数具有类似的逻辑。

    // Stop at 0
    for (let i = number; i > 0; i--)

    Again, loops need extra state to determine when they should stop. That's what x and i are for.

    同样,循环需要额外的状态来确定何时停止。 这就是xi是。

    无限递归 (Infinite Recursion)

    Recursion also presents the same danger. It's not hard to write a self-referencing function that'll crash your browser.

    递归也存在同样的危险。 编写会导致浏览器崩溃的自引用功能并不难。

    🚨THIS RUNS FOREVER, BE WARNED🚨
    function run() {
        console.log('running');
        run();
    }
    
    run();
    // running
    // running
    // ...

    is-this-a-recursive

    Without a stopping condition, run will forever call itself. You can fix that with an if statement.

    在没有停止条件的情况下, run将永远自我调用。 您可以使用if语句解决该问题。

    ✅ This does not run forever
    
    function run(x) {
        if (x === 3) return;
        
        console.log('running');
        run(x + 1);
    }
    
    run(0);
    // running
    // running
    // running
    
    // x is 3 now, we're done.

    基本情况 (Base case)

    This is known as the base case–our recursive countDownFrom had one.

    这被称为基本案例–我们的递归countDownFrom有一个。

    if (number === 0) {
        return;
    }

    It's the same idea as our loop's stopping logic. Whichever approach you pick, always remember that at some point it needs to be stopped.

    这与循环的停止逻辑相同。 无论选择哪种方法,请始终记住,必须在某个时候停止它

    is-this-you-need-to-be-stopped

    摘要 (Summary)

    • Recursion is when a function calls itself until someone stops it.

      递归是一个函数调用自身直到有人停止它的时间。
    • It can be used instead of a loop.

      可以使用它代替循环。
    • If no one stops it, it'll recurse forever and crash your program.

      如果没有人停止它,它将永远递归并崩溃您的程序。
    • A base case is a condition that stops the recursion. Don't forget to add them!

      基本情况是停止递归的条件。 不要忘记添加它们!

    • Loops use extra state variables for tracking and counting, while recursion only uses the provided parameters.

      循环使用额外的状态变量进行跟踪和计数,而递归仅使用提供的参数。

    disappearing-loops

    谢谢阅读 (Thanks for reading)

    For more content like this, check out https://yazeedb.com. And please let me know what else you'd like to see! My DMs are open on Twitter.

    有关此类的更多内容,请访问https://yazeedb.com 。 并且,请让我知道您还想看到什么! 我的DM在Twitter上打开。

    Until next time!

    直到下一次!

    翻译自: https://www.freecodecamp.org/news/quick-intro-to-recursion/

    java 快速排序 递归

    展开全文
  • Java实现递归下降子程序 一、实验目的 根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实 验的目的主要是加深对递归下降分析法的理解。 二、实验内容 程序输入/输出示例(以下仅供参考...
  • Java写一个简单的递归程序递归的定义递归(recursion):以此类推是递归的基本思想,将规模大的问题转化为规模小的问题来解决。递归的要素自定义递归函数,并确定函数的基本功能例如Java从键盘输入一个数,求输入这...
  • java递归算法详解

    2021-02-28 18:20:09
    Java中的递归算法虽然简单,但想要精通也是有着一定的难度的,本篇文章我们就来详细了解下递归算法。什么是递归?一般的说, 递归算法是一种直接或间接地调用自身的算法。在程序中,递归算法能够使算法的描述简洁而且...
  • java递归的深度

    2021-03-21 10:16:24
    递归的深度在使用递归的时候经常会抛出StackOverflowError,顾名思义就是栈满了,而我们这里所说的栈在java中通常就是虚拟机栈(vm stack),在每个方法执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈,...
  • java递归面试题

    2021-02-13 00:38:44
    题目1:斐波那契数列一列数的... 求第30位数是多少, 用递归算法实现。public static int getFabonacciSequenceByNum(int num){//exitif(num ==1||num ==2){return 1;}//logicreturn getFabonacciSequenceByNum(num-...
  • Java递归计算1加到100

    千次阅读 2019-08-22 23:36:43
    Java递归计算1加到100 package demo public class DiGui{ public static void main(String[] args){ System.out.println(digui(100)); } public static int digui(int n){ int sum = 0; if(n == 1){ ...
  • 1.所谓的递归慢到底是什么原因呢?大家都知道递归的实现是通过调用函数本身,函数调用的时候,每次调用时要做地址保存,参数传递等,这是通过一个递归工作栈实现的。具体是每次调用函数本身要保存的内容包括:局部...
  • 这是一个程序,读取信息网站为以前的格式,它使用...java中执行程序如何终止递归?public class NewClass {static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" };static String links = "";pri...
  • 这是一个程序,它读取以前格式的信息站点,它使用递归和执行器.它工作正常,我的问题是测试程序是否完成和成功通知.public class NewClass {static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" };...
  • java递归是什么意思,java递归怎么用?程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。但是如果没终止条件会造成死循环,所以递归代码里要有结束自调自的条件。接下来通过...
  • 程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题...
  • Java 递归的方法求年龄,一个有意思的数学问题:有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。  public static void main(String[] args) {   TestAge ta = new TestAge();//创建类的一个实例   ...
  • Java递归的原理以及各种案例演示

    千次阅读 2020-03-28 11:07:27
    介绍Java中的递归以及代码演示,比如求递归阶乘、递归求和、递归求二进制数、递归遍历文件目录等。
  • Java递归详解

    千次阅读 多人点赞 2019-03-25 18:30:05
    Java递归算法是基于Java语言实现的递归算法。递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。递归算法对解决一大类问题很有效,它可以使算法简洁和易于理解。 递归...
  • java关于递归

    2021-03-21 10:52:09
    此种函数就称为递归函数递归函数的优点是程序简洁易懂,可读性强;缺点是需要调用大量的函数调用,消耗大量的内存和时间一般来说,递归由函数出口和递归体两部分组成,递归出口给出了递归终止条件,递归体给出了递归的方式...
  • Java 递归算法

    千次阅读 2020-01-07 00:29:25
    Java递归:简单说就是函数自身直接或间接调用函数的本身。 二、应用场景: 若:一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关,这时就可以使用递归来解决这个问题。 使用要点: 1,...
  • 参考C语言版本,用Java写的递归下降分析程序,能对词法分析程序所提供的单词序列进行语法检查和结构分析。被分析的语言应该是PL/0,语法表示如下: (1)<程序>::=begin<语句串>end (2)<语句串>::=<语句>{;...
  • Java 递归结束

    千次阅读 2017-11-27 17:28:31
    希望递归结束后去更新UI界面。那什么时候才是递归结束呢。网上有人去判断一个固定参数,然后结束,简直莫名其妙,这个固定参数居然是随便乱取的,不科学。 思路: 根据判断i=0,收集size的值。通过i=0,收集到循环...
  • 对于文法: E->TG G->+TG|-TG|ε T->FS S->*FS|/FS|ε F->(E)|i 用递归下降分析法对任意输入的符号串进行分析,输入输出参考main函数。
  • 什么是递归?用Java写一个简单的递归程序

    千次阅读 多人点赞 2021-02-17 14:33:45
    Java写一个简单的递归程序 递归的定义 递归(recursion):以此类推是递归的基本思想,将规模大的问题转化为规模小的问题来解决。 递归的要素 自定义递归函数,并确定函数的基本功能 例如Java从键盘输入一个数,...
  • Java 递归详解

    千次阅读 2018-04-16 16:01:33
    递归详解:1.递归一句话通俗讲就是一个方法自动重复调用自己的过程。2.因为是重复调用自己了,所以看起来像一个循环,所以为了避免内存溢出系统崩溃,我们需要在方法里加一个返回值判断,用于递归循环的跳出。下面用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 161,108
精华内容 64,443
关键字:

java递归程序

java 订阅