什么是递归

时间:2012-11-30 13:47:20

标签: java recursion

  

可能重复:
  Examples of Recursive functions

我一直在尝试将编程中的递归作为一个概念进行研究(虽然我专门研究Java),这就是我最了解的内容:

  

在现实生活中,例如,递归是指我们将两个镜子放在彼此面前并且它们之间产生的图像是递归的。

但是我没有在编程中得到这个算法? 有人能给我一个简化的例子来理解递归吗?

6 个答案:

答案 0 :(得分:19)

递归是一种编程技术,其中方法可以将自身称为其计算的一部分(有时您可以使用多个方法 - 这些方法通常会循环地相互调用)。

一个流行的例子是计算Fibonacci numbers

public static long fib(int n) {
    if (n <= 1) return n;
    else return fib(n-1) + fib(n-2);
}

两个基本组件是基本案例(示例中为n<=1)和递归案例。

在创建递归算法时,你需要考虑基本情况以及如何使用递归的情况你将得到基本情况(否则你最终会得到无限递归并吹掉堆栈)。

答案 1 :(得分:6)

基本上,当

时,函数是递归的
  1. 一个函数有一个简单的基本情况,当
  2. 所有其他案件都有适用于基本情况的规则。
  3. 例如,计算一个阶乘:

    public static long factorial(int i)
    {
        // This is the base case
        if(i == 0)
        {
             return 1;
        }
        else
        {
            // This reduces the problem to something closer to the base case
            return i * factorial(i - 1);
        }
    }
    

答案 2 :(得分:2)

递归编程是一种基于mathematical induction概念的技术,其中方法或函数重复调用自身。因此,可以按如下方式实现阶乘函数:

int fact(int n) {
    if (n < 2) {
            return 1;
    }

    return n * fact(n-1);
}

请注意,为了确保递归终止,您应该确保处理一个基本情况,即为某些已知的简单输入定义常量输出,并且您应该确保使函数的参数更简单。每次迭代(在上面的示例中,将n减少1)。

答案 3 :(得分:2)

可以用这样的方式描述一些计算问题,即问题可以分解为较小的子问题。使用与主要问题相同的方法解决较小的子问题。如果较小的子问题只是较大问题的较小情况,那么本身可以进一步细分。

最终,问题是如此之小,以至于无需进一步分解即可解决问题。这被称为基本情况。通过基本案例的解决方案,您可以构建解决更大问题的解决方案。

假设你想找到一个 b ,其中a和b是正整数。您可以看到这与a * a (b-1)相同。也就是说,(b-1)是比原始问题更小的问题,但仍然需要与原始问题相同的技术来解决。要解决(b-1),你会发现它是* a (b-2)

等等。

最终你得到一个* a * a * ... * a (b-b)。我们知道b-b = 0且 0 = 1.所以我们不必考虑最后一点,因为我们已经知道了答案。最终, b = a * a * a * ... * 1.

所以2 4 = 2 * 2 3 = 2 * 2 * 2 2 = 2 * 2 * 2 * 2 1 = 2 * 2 * 2 * 2 * 2 0 = 2 * 2 * 2 * 2 * 1.

要编写此程序,首先要处理基本案例,然后使用递归来处理其他所有内容。

   pow(a, b){
       if(b == 0){
          return 1;
       }else{

          return a * pow(a, b - 1);
       }
   }

重要的是要注意,这只是递归的基本思想。您在各种答案中看到的这些例子,例如斐波纳契数问题,效率非常低。您可以使用动态编程技术构建更高效的程序,该技术使用递归作为解决问题的机制之一。

答案 4 :(得分:1)

非常简单的'递归'代码。

处理列表的顶部项目。将其从列表中删除并调用代码来处理列表的顶部项目。

树根有一定的长度,每2/3根分裂成单独的根。分裂的碎片每2/3根分裂成单独的根。拆分的碎片分开了......等等。

答案 5 :(得分:1)

递归

方法可以调用自身,这是递归。通常使用递归的方法实现,因为它们导致紧凑的优雅代码,这比不使用递归的相应实现更容易理解。

递归编程技术知道三个重要的规则(拇指):

  1. 基本案例:递归具有基本案例。始终第一个陈述是有条件的,并且有一个'返回'。
  2. SubProblem :递归调用可以解决在某种意义上较小的子问题,以便它收敛到基本情况
  3. No Overlapping :递归调用不应处理重叠的子问题。
  4. 从性能的角度来看,非递归解决方案更快,并且通常需要更少的内存。 (例如二元搜索)
    但是有些任务非常复杂,只有递归解决方案才能产生(或多或少可理解的)代码。

    递归二进制搜索的示例:

    public static int binSearch(int[] a, int key) {
       return binSearch0(a, key, 0, a.length - 1);
    }
    
    public static int binSearch0(int[] a, int key, int from, int to) {
        if (from > to) return -1;
        // looks strange but (from + to) / 2 can oveflow
        // (java bug which was active more than 10 years)
        int mid = from + (to - from) / 2;
        if (key < a[mid]) 
            return binSearch0(a, key, from, mid - 1);
        else if (key < a[mid]) 
            return binSearch0(a, key, mid + 1, to);
        else return mid;
     }
    

    在该示例中,您可以看到所有三个规则(base,sub,non oberlap) 并非递归函数通常具有启动函数,示例中为“binSearch”。其中'binSearch0'是递归函数。

相关问题