📜  递归

📅  最后修改于: 2021-04-30 02:19:01             🧑  作者: Mango

什么是递归?
函数直接或间接调用自身的过程称为递归,而相应的函数称为递归函数。使用递归算法,可以很容易地解决某些问题。此类问题的示例包括河内塔(TOH),有序/预排序/后序树遍历,图的DFS等。

数学解释

让我们考虑一个问题,程序员必须确定前n个自然数之和,有几种方法可以做到这一点,但是最简单的方法是简单地将1到n之间的数字相加。因此,该函数看起来就像

但是还有另一种数学方法来表示这一点,

方法(1)和方法(2)之间有一个简单的区别,即在方法(2)中,函数“ f() ”本身在函数内部被调用,因此此现象称为递归,并且函数包含递归称为递归函数,最后这是程序员手中一个很好的工具,它可以以更轻松,更有效的方式对一些问题进行编码。

递归的基本条件是什么?
在递归程序中,提供了对基本情况的解决方案,并且以较小的问题表示较大的问题的解决方案。

int fact(int n)
{
    if (n < = 1) // base case
        return 1;
    else    
        return n*fact(n-1);    
}

在上面的示例中,定义了n <= 1的基本情况,并且可以通过转换为较小的1直至达到基本情况来解决较大的数值。

如何使用递归解决特定问题?
这个想法是用一个或多个较小的问题来表示一个问题,并添加一个或多个停止递归的基本条件。例如,如果我们知道(n-1)的阶乘,就可以计算阶乘n。阶乘的基本情况为n =0。当n = 0时,我们返回1。

为什么在递归中发生堆栈溢出错误?
如果未达到或未定义基本情况,则可能会出现堆栈溢出问题。让我们以一个例子来理解这一点。

int fact(int n)
{
    // wrong base case (it may cause
    // stack overflow).
    if (n == 100) 
        return 1;

    else
        return n*fact(n-1);
}

如果调用fact(10),它将调用fact(9),fact(8),fact(7)等,但数量永远不会达到100。因此,不会达到基本情况。如果堆栈上的这些功能耗尽了内存,则会导致堆栈溢出错误。

直接和间接递归有什么区别?
如果函数调用相同的函数,则称为直接递归。如果fun函数调用另一个函数,例如fun_new和fun_new直接或间接调用fun,则该函数称为间接递归。表1说明了直接和间接递归之间的区别。

// An example of direct recursion
void directRecFun()
{
    // Some code....

    directRecFun();

    // Some code...
}

// An example of indirect recursion
void indirectRecFun1()
{
    // Some code...

    indirectRecFun2();

    // Some code...
}
void indirectRecFun2()
{
    // Some code...

    indirectRecFun1();

    // Some code...
}

尾递归和非尾递归之间有什么区别?
当递归调用是该函数执行的最后一件事时,递归函数就是尾部递归。有关详细信息,请参阅尾递归文章。

如何在递归中将内存分配给不同的函数调用?
从main()调用任何函数,都会在堆栈上为其分配内存。递归函数调用自身,被调用函数的内存分配在分配给调用函数的内存之上,并且为每个函数调用创建不同的局部变量副本。当达到基本情况时,该函数将其值返回给调用该函数,并取消分配内存,然后过程继续进行。
让我们以一个简单的函数为例,说明递归的工作原理。

CPP
// A C++ program to demonstrate working of
// recursion
#include 
using namespace std;
 
void printFun(int test)
{
    if (test < 1)
        return;
    else {
        cout << test << " ";
        printFun(test - 1); // statement 2
        cout << test << " ";
        return;
    }
}
 
// Driver Code
int main()
{
    int test = 3;
    printFun(test);
}


Java
// A Java program to demonstrate working of
// recursion
class GFG {
    static void printFun(int test)
    {
        if (test < 1)
            return;
        else {
            System.out.printf("%d ", test);
            printFun(test - 1); // statement 2
            System.out.printf("%d ", test);
            return;
        }
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int test = 3;
        printFun(test);
    }
}
 
// This code is contributed by
// Smitha Dinesh Semwal


Python3
# A Python 3 program to
# demonstrate working of
# recursion
 
 
def printFun(test):
 
    if (test < 1):
        return
    else:
 
        print(test, end=" ")
        printFun(test-1)  # statement 2
        print(test, end=" ")
        return
 
# Driver Code
test = 3
printFun(test)
 
# This code is contributed by
# Smitha Dinesh Semwal


C#
// A C# program to demonstrate
// working of recursion
using System;
 
class GFG {
 
    // function to demonstrate
    // working of recursion
    static void printFun(int test)
    {
        if (test < 1)
            return;
        else {
            Console.Write(test + " ");
 
            // statement 2
            printFun(test - 1);
 
            Console.Write(test + " ");
            return;
        }
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int test = 3;
        printFun(test);
    }
}
 
// This code is contributed by Anshul Aggarwal.


PHP


Javascript


C++
// C++ code to implement Fibonacci series
#include 
using namespace std;
 
// Function for fibonacci
 
int fib(int n)
{
    // Stop condition
    if (n == 0)
        return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
        return 1;
 
    // Recursion function
    else
        return (fib(n - 1) + fib(n - 2));
}
 
// Driver Code
int main()
{
    // Initialize variable n.
    int n = 5;
    cout<<"Fibonacci series of 5 numbers is: ";
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++)
    {
        cout<


C
// C code to implement Fibonacci series
#include 
 
// Function for fibonacci
int fib(int n)
{
    // Stop condition
    if (n == 0)
        return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
        return 1;
 
    // Recursion function
    else
        return (fib(n - 1) + fib(n - 2));
}
 
// Driver Code
int main()
{
    // Initialize variable n.
    int n = 5;
    printf("Fibonacci series "
           "of %d numbers is: ",
           n);
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++) {
        printf("%d ", fib(i));
    }
    return 0;
}


Java
// Java code to implement Fibonacci series
import java.util.*;
 
class GFG
{
 
// Function for fibonacci
static int fib(int n)
{
    // Stop condition
    if (n == 0)
        return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
        return 1;
 
    // Recursion function
    else
        return (fib(n - 1) + fib(n - 2));
}
 
// Driver Code
public static void main(String []args)
{
   
    // Initialize variable n.
    int n = 5;
    System.out.print("Fibonacci series of 5 numbers is: ");
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++)
    {
        System.out.print(fib(i)+" ");
    }
}
}
 
// This code is contributed by rutvik_56.


Python3
# Python code to implement Fibonacci series
 
# Function for fibonacci
def fib(n):
 
    # Stop condition
    if (n == 0):
        return 0
 
    # Stop condition
    if (n == 1 or n == 2):
        return 1
 
    # Recursion function
    else:
        return (fib(n - 1) + fib(n - 2))
 
 
# Driver Code
 
# Initialize variable n.
n = 5;
print("Fibonacci series of 5 numbers is :",end=" ")
 
# for loop to print the fiboancci series.
for i in range(0,n):
    print(fib(i),end=" ")


C#
using System;
 
public class GFG
{
 
  // Function for fibonacci
  static int fib(int n)
  {
 
    // Stop condition
    if (n == 0)
      return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
      return 1;
 
    // Recursion function
    else
      return (fib(n - 1) + fib(n - 2));
  }
 
  // Driver Code
  static public void Main ()
  {
 
    // Initialize variable n.
    int n = 5;
    Console.Write("Fibonacci series of 5 numbers is: ");
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++)
    {
      Console.Write(fib(i) + " ");
    }
  }
}
 
// This code is contributed by avanitrachhadiya2155


Javascript


C++
// C++ code to implement factorial
#include 
using namespace std;
 
// Factorial function
int f(int n)
{
    // Stop condition
    if (n == 0 || n == 1)
        return 1;
 
    // Recursive condition
    else
        return n * f(n - 1);
}
 
// Driver code
int main()
{
    int n = 5;
    cout<<"factorial of "<


C
// C code to implement factorial
#include 
 
// Factorial function
int f(int n)
{
    // Stop condition
    if (n == 0 || n == 1)
        return 1;
 
    // Recursive condition
    else
        return n * f(n - 1);
}
 
// Driver code
int main()
{
    int n = 5;
    printf("factorial of %d is: %d", n, f(n));
    return 0;
}


Java
// Java code to implement factorial
public class GFG
{
 
  // Factorial function
  static int f(int n)
  {
 
    // Stop condition
    if (n == 0 || n == 1)
      return 1;
 
    // Recursive condition
    else
      return n * f(n - 1);
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int n = 5;
    System.out.println("factorial of " + n + " is: " + f(n));
  }
}
 
// This code is contributed by divyesh072019.


Python3
# Python3 code to implement factorial
 
# Factorial function
def f(n):
 
    # Stop condition
    if (n == 0 or n == 1):
        return 1;
 
    # Recursive condition
    else:
        return n * f(n - 1);
 
 
# Driver code
if __name__=='__main__':
 
    n = 5;
    print("factorial of",n,"is:",f(n))
     
    # This code is contributed by pratham76.


C#
// C# code to implement factorial
using System;
class GFG {
 
  // Factorial function
  static int f(int n)
  {
    // Stop condition
    if (n == 0 || n == 1)
      return 1;
 
    // Recursive condition
    else
      return n * f(n - 1);
  }
 
  // Driver code
  static void Main()
  {
    int n = 5;
    Console.WriteLine("factorial of " + n + " is: " + f(n));
  }
}
 
// This code is contributed by divyeshrabadiya07.


Javascript


输出 :

3 2 1 1 2 3

当从main()调用printFun(3)时,将内存分配给printFun(3),并将局部变量test初始化为3,并将语句1到4压入堆栈,如下图所示。它首先打印“ 3”。在语句2中,调用printFun(2)并将内存分配给printFun(2),并将局部变量test初始化为2,并将语句1至4压入堆栈。同样, printFun(2)调用printFun(1),printFun(1)调用printFun(0)printFun(0)转到if语句,然后返回到printFun(1) 。执行剩余的printFun(1)语句,并返回到printFun(2) ,依此类推。在输出中,从3到1的值被打印,然后从1到3的值被打印。下图显示了内存堆栈。

递归

现在,让我们讨论一些可以通过使用递归解决的实际问题,并了解其基本工作原理。为了基本了解,请阅读以下文章。
对递归的基本了解。
问题1:编写程序和递归关系以找到n的斐波那契数列,其中n> 2。
数学方程式:

n if n == 0, n == 1;      
fib(n) = fib(n-1) + fib(n-2) otherwise;

递归关系:

T(n) = T(n-1) + T(n-2) + O(1)

递归程序:

Input: n = 5 
Output:
Fibonacci series of 5 numbers is : 0 1 1 2 3

执行:

C++

// C++ code to implement Fibonacci series
#include 
using namespace std;
 
// Function for fibonacci
 
int fib(int n)
{
    // Stop condition
    if (n == 0)
        return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
        return 1;
 
    // Recursion function
    else
        return (fib(n - 1) + fib(n - 2));
}
 
// Driver Code
int main()
{
    // Initialize variable n.
    int n = 5;
    cout<<"Fibonacci series of 5 numbers is: ";
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++)
    {
        cout<

C

// C code to implement Fibonacci series
#include 
 
// Function for fibonacci
int fib(int n)
{
    // Stop condition
    if (n == 0)
        return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
        return 1;
 
    // Recursion function
    else
        return (fib(n - 1) + fib(n - 2));
}
 
// Driver Code
int main()
{
    // Initialize variable n.
    int n = 5;
    printf("Fibonacci series "
           "of %d numbers is: ",
           n);
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++) {
        printf("%d ", fib(i));
    }
    return 0;
}

Java

// Java code to implement Fibonacci series
import java.util.*;
 
class GFG
{
 
// Function for fibonacci
static int fib(int n)
{
    // Stop condition
    if (n == 0)
        return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
        return 1;
 
    // Recursion function
    else
        return (fib(n - 1) + fib(n - 2));
}
 
// Driver Code
public static void main(String []args)
{
   
    // Initialize variable n.
    int n = 5;
    System.out.print("Fibonacci series of 5 numbers is: ");
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++)
    {
        System.out.print(fib(i)+" ");
    }
}
}
 
// This code is contributed by rutvik_56.

Python3

# Python code to implement Fibonacci series
 
# Function for fibonacci
def fib(n):
 
    # Stop condition
    if (n == 0):
        return 0
 
    # Stop condition
    if (n == 1 or n == 2):
        return 1
 
    # Recursion function
    else:
        return (fib(n - 1) + fib(n - 2))
 
 
# Driver Code
 
# Initialize variable n.
n = 5;
print("Fibonacci series of 5 numbers is :",end=" ")
 
# for loop to print the fiboancci series.
for i in range(0,n):
    print(fib(i),end=" ")

C#

using System;
 
public class GFG
{
 
  // Function for fibonacci
  static int fib(int n)
  {
 
    // Stop condition
    if (n == 0)
      return 0;
 
    // Stop condition
    if (n == 1 || n == 2)
      return 1;
 
    // Recursion function
    else
      return (fib(n - 1) + fib(n - 2));
  }
 
  // Driver Code
  static public void Main ()
  {
 
    // Initialize variable n.
    int n = 5;
    Console.Write("Fibonacci series of 5 numbers is: ");
 
    // for loop to print the fiboancci series.
    for (int i = 0; i < n; i++)
    {
      Console.Write(fib(i) + " ");
    }
  }
}
 
// This code is contributed by avanitrachhadiya2155

Java脚本


输出
Fibonacci series of 5 numbers is: 0 1 1 2 3 

这是输入5的递归树,它清楚地显示了如何将大问题解决为较小的问题。
fib(n)是斐波那契函数。给定程序的时间复杂度可能取决于函数调用。

为最好的情况。

T(n) =   θ(2^n\2)

在职的:

问题2:编写程序和递归关系以找到n的阶乘,其中n> 2。
数学方程:

1 if n == 0 or n == 1;      
f(n) = n*f(n-1) if n> 1;

递归关系:

T(n) = 1 for n = 0
T(n) = 1 + T(n-1) for n > 0

递归程序:
输入: n = 5
输出:
5的阶乘是:120
执行:

C++

// C++ code to implement factorial
#include 
using namespace std;
 
// Factorial function
int f(int n)
{
    // Stop condition
    if (n == 0 || n == 1)
        return 1;
 
    // Recursive condition
    else
        return n * f(n - 1);
}
 
// Driver code
int main()
{
    int n = 5;
    cout<<"factorial of "<

C

// C code to implement factorial
#include 
 
// Factorial function
int f(int n)
{
    // Stop condition
    if (n == 0 || n == 1)
        return 1;
 
    // Recursive condition
    else
        return n * f(n - 1);
}
 
// Driver code
int main()
{
    int n = 5;
    printf("factorial of %d is: %d", n, f(n));
    return 0;
}

Java

// Java code to implement factorial
public class GFG
{
 
  // Factorial function
  static int f(int n)
  {
 
    // Stop condition
    if (n == 0 || n == 1)
      return 1;
 
    // Recursive condition
    else
      return n * f(n - 1);
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int n = 5;
    System.out.println("factorial of " + n + " is: " + f(n));
  }
}
 
// This code is contributed by divyesh072019.

Python3

# Python3 code to implement factorial
 
# Factorial function
def f(n):
 
    # Stop condition
    if (n == 0 or n == 1):
        return 1;
 
    # Recursive condition
    else:
        return n * f(n - 1);
 
 
# Driver code
if __name__=='__main__':
 
    n = 5;
    print("factorial of",n,"is:",f(n))
     
    # This code is contributed by pratham76.

C#

// C# code to implement factorial
using System;
class GFG {
 
  // Factorial function
  static int f(int n)
  {
    // Stop condition
    if (n == 0 || n == 1)
      return 1;
 
    // Recursive condition
    else
      return n * f(n - 1);
  }
 
  // Driver code
  static void Main()
  {
    int n = 5;
    Console.WriteLine("factorial of " + n + " is: " + f(n));
  }
}
 
// This code is contributed by divyeshrabadiya07.

Java脚本


输出
factorial of 5 is: 120

在职的:

用户输入的阶乘递归函数图5。

与迭代编程相比,递归编程有哪些缺点?
请注意,递归程序和迭代程序都具有相同的解决问题的能力,即,每个递归程序都可以迭代地编写,反之亦然。递归程序比迭代程序具有更大的空间要求,因为所有功能都将保留在堆栈中,直到达到基本情况为止。由于函数调用和返回开销,它也有更多的时间要求。

递归编程比迭代编程有什么优势?
递归提供了一种干净且简单的编写代码的方法。有些问题本质上是递归的,例如遍历树,河内塔等。对于此类问题,最好编写递归代码。我们还可以借助堆栈数据结构来迭代地编写此类代码。例如,请参阅“无递归的有序树遍历,河内迭代塔”。