Tipos de recurrencias

¿Qué es la recursividad ?  
El proceso en el que una función se llama a sí misma directa o indirectamente se llama recursividad y la función correspondiente se llama función recursiva. Usando el algoritmo recursivo, ciertos problemas se pueden resolver con bastante facilidad. Ejemplos de tales problemas son Towers of Hanoi (TOH) , Inorder/Preorder/Postorder Tree Traversals , DFS of Graph , etc.

Tipos de recurrencias : 
Las recurrencias son principalmente de dos tipos dependiendo de si una función se llama a sí misma desde dentro de sí misma o más de una función se llama entre sí. La primera se llama recursión directa y la otra se llama recursión indirecta . Así, los dos tipos de recursividad son:

1. Recursión directa : se pueden clasificar en cuatro tipos :

  • Tail Recursion : si una función recursiva se llama a sí misma y esa llamada recursiva es la última declaración en la función, entonces se conoce como Tail Recursion. Después de esa llamada, la función recursiva no realiza nada. La función tiene que procesar o realizar alguna operación en el momento de la llamada y no hace nada en el momento de la devolución.
    Ejemplo:

C++

// Code Showing Tail Recursion
#include <iostream>
using namespace std;
 
// Recursion function
void fun(int n)
{
    if (n > 0) {
        cout << n << " ";
 
        // Last statement in the function
        fun(n - 1);
    }
}
 
// Driver Code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}
 
// This code is contributed by shubhamsingh10

C

// Code Showing Tail Recursion
 
#include <stdio.h>
 
// Recursion function
void fun(int n)
{
    if (n > 0) {
        printf("%d ", n);
 
        // Last statement in the function
        fun(n - 1);
    }
}
 
// Driver Code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}

Java

// Java code Showing Tail Recursion
class GFG {
 
  // Recursion function
  static void fun(int n)
  {
    if (n > 0)
    {
      System.out.print(n + " ");
 
      // Last statement in the function
      fun(n - 1);
    }
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int x = 3;
    fun(x);
  }
}
 
// This code is contributed by pratham76.

Python3

# Code Showing Tail Recursion
 
# Recursion function
def fun(n):
    if (n > 0):
        print(n, end=" ")
        # Last statement in the function
        fun(n - 1)
 
# Driver Code
x = 3
fun(x)
 
# This code is contributed by Shubhamsingh10

C#

// C# code Showing Tail Recursion
using System;
 
class GFG
{
 
  // Recursion function
  static void fun(int n)
  {
    if (n > 0)
    {
      Console.Write(n + " ");
 
      // Last statement in the function
      fun(n - 1);
    }
  }
 
  // Driver Code
  public static void Main(string[] args)
  {
    int x = 3;
    fun(x);
  }
}
 
// This code is contributed by rutvik_56

Javascript

<script>
// Javascript code Showing Tail Recursion
  // Recursion function
   function fun(n)
  {
    if (n > 0)
    {
      document.write(n + " ");
 
      // Last statement in the function
      fun(n - 1);
    }
  }
 
  // Driver Code
   
    var x = 3;
    fun(x);
   
// This code is contributed by shivanisinghss2110
</script>
Producción

3 2 1 

Entendamos el ejemplo rastreando el árbol de la función recursiva. Así es como se hacen las llamadas y así se producen las salidas.

Complejidad de tiempo para recurrencia de cola: O(n)  
Complejidad de espacio para recurrencia de cola: O(n)
Nota: Complejidad de tiempo y espacio se proporciona para este ejemplo específico. Puede variar para otro ejemplo.

Ahora, convirtamos Tail Recursion en Loop y comparemos entre sí en términos de Complejidad de tiempo y espacio y decidamos cuál es más eficiente.

C++

// Converting Tail Recursion into Loop
#include <iostream>
using namespace std;
 
void fun(int y)
{
    while (y > 0) {
        cout << y << " ";
        y--;
    }
}
 
// Driver code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}
 
//This Code is contributed by Shubhamsingh10

C

// Converting Tail Recursion into Loop
 
#include <stdio.h>
 
void fun(int y)
{
    while (y > 0) {
        printf("%d ", y);
        y--;
    }
}
 
// Driver code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}

Java

// Converting Tail Recursion into Loop
import java.io.*;
class GFG
{
static void fun(int y)
{
    while (y > 0) {
        System.out.print(" "+ y);
        y--;
    }
}
 
// Driver code
public static void main(String[] args)
{
    int x = 3;
    fun(x);
     
}
}
 
// This code is contributed by shivanisinghss2110

Python3

# Converting Tail Recursion into Loop
def fun(y):
 
    while (y > 0):
        print(y , end = " ")
        y -= 1
     
# Driver code
x = 3
fun(x)
 
# This Code is contributed by shivanisinghss2110

C#

// Converting Tail Recursion into Loop
using System;
class GFG
{
static void fun(int y)
{
    while (y > 0) {
        Console.Write(" "+ y);
        y--;
    }
}
 
// Driver code
public static void Main(String[] args)
{
    int x = 3;
    fun(x);
     
}
}
// This code is contributed by shivanisinghss2110

Javascript

<script>
function fun(y)
{
    while (y > 0) {
        document.write(" "+ y);
        y--;
    }
}
 
// Driver code
  var x = 3;
    fun(x);
 
// This code is contributed by shivanisinghss2110
</script>
Producción

3 2 1 

Complejidad de tiempo: O(n)  
Complejidad de espacio: O(1)

Nota: Complejidad de tiempo y espacio se proporciona para este ejemplo específico. Puede variar para otro ejemplo.
Entonces, se vio que en el caso de bucle, la Complejidad espacial es O (1), por lo que era mejor escribir código en bucle en lugar de recurrir a la cola en términos de Complejidad espacial, que es más eficiente que la recursión a la cola.

¿Por qué la complejidad del espacio es menor en el caso del bucle?
Antes de explicar esto, supongo que está familiarizado con el conocimiento de cómo se almacenan los datos en la memoria principal durante la ejecución de un programa. En resumen, cuando se ejecuta el programa, la memoria principal se divide en tres partes. Una parte para la sección de código, la segunda es la memoria de montón y otra es la memoria de pila. Recuerde que el programa puede acceder directamente solo a la memoria de la pila, no puede acceder directamente a la memoria del montón, por lo que necesitamos la ayuda del puntero para acceder a la memoria del montón.

Ahora entendamos por qué la complejidad del espacio es menor en el caso del bucle.
En caso de bucle, cuando la función «(void fun(int y))» se ejecuta allí, solo se crea un registro de activación en la memoria de la pila (registro de activación creado solo para la variable ‘y’), por lo que solo se necesita ‘una’ unidad de memoria dentro de la pila, por lo que su complejidad de espacio es O (1) pero en el caso de la función recursiva cada vez que se llama a sí mismo para cada llamada, se crea un registro de activación separado en la pila. Entonces, si hay ‘n’ no de llamada, entonces toma ‘n’ unidad de memoria dentro de la pila entonces su complejidad espacial es O(n). 

  • Head Recursion : si una función recursiva se llama a sí misma y esa llamada recursiva es la primera declaración en la función, entonces se conoce como Head Recursion. No hay declaración, no hay operación antes de la llamada. La función no tiene que procesar ni realizar ninguna operación en el momento de la llamada y todas las operaciones se realizan en el momento de la devolución.
    Ejemplo:

C++

// C++ program showing Head Recursion
 
#include <bits/stdc++.h>
using namespace std;
 
// Recursive function
void fun(int n)
{
    if (n > 0) {
 
        // First statement in the function
        fun(n - 1);
 
        cout << " "<< n;
    }
}
 
// Driver code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}
 
// this code is contributed by shivanisinghss2110

C

// C program showing Head Recursion
 
#include <stdio.h>
 
// Recursive function
void fun(int n)
{
    if (n > 0) {
 
        // First statement in the function
        fun(n - 1);
 
        printf("%d ", n);
    }
}
 
// Driver code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}

Java

// Java program showing Head Recursion
import java.io.*;
  
class GFG{
     
// Recursive function
static void fun(int n)
{
    if (n > 0) {
 
        // First statement in the function
        fun(n - 1);
 
        System.out.print(" "+ n);
    }
}
 
// Driver code
public static void main(String[] args)
{
    int x = 3;
    fun(x);
     
}
}
 
// This code is contributed by shivanisinghss2110

Python3

# Python program showing Head Recursion
# Recursive function
def fun(n):
 
    if (n > 0):
 
        # First statement in the function
        fun(n - 1)
 
        print(n,end=" ")
     
 
 
# Driver code
x = 3
fun(x)
 
 
# this code is contributed by shivanisinghss2110

C#

// Java program showing Head Recursion
using System;
  
class GFG{
     
// Recursive function
static void fun(int n)
{
    if (n > 0) {
 
        // First statement in the function
        fun(n - 1);
 
        Console.Write(" "+ n);
    }
}
 
// Driver code
public static void Main(String[] args)
{
    int x = 3;
    fun(x);
     
}
}
 
// This code is contributed by shivanisinghss2110

Javascript

<script>
 
// JavaScript program showing Head Recursion
// Recursive function
function fun(n)
{
    if (n > 0) {
 
        // First statement in the function
        fun(n - 1);
 
        document.write(" "+ n);
    }
}
 
// Driver code
    var x = 3;
    fun(x);
 
// This code is contributed by shivanisinghss2110
 
</script>
Producción

 1 2 3

Entendamos el ejemplo rastreando el árbol de la función recursiva. Así es como se hacen las llamadas y así se producen las salidas.

Complejidad de tiempo para la recurrencia principal: O(n)  
Complejidad espacial para la recurrencia principal: O(n)

Nota: Complejidad de tiempo y espacio se proporciona para este ejemplo específico. Puede variar para otro ejemplo.
Nota: La recursividad principal no se puede convertir fácilmente en un bucle como recursividad de cola, pero puede hacerlo. Convirtamos el código anterior en el bucle.

C++

// Converting Head Recursion into Loop
#include <iostream>
using namespace std;
 
// Recursive function
void fun(int n)
{
    int i = 1;
    while (i <= n) {
        cout <<" "<< i;
        i++;
    }
}
 
// Driver code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}
// this code is contributed by shivanisinghss2110

C

// Converting Head Recursion into Loop
 
#include <stdio.h>
 
// Recursive function
void fun(int n)
{
    int i = 1;
    while (i <= n) {
        printf("%d ", i);
        i++;
    }
}
 
// Driver code
int main()
{
    int x = 3;
    fun(x);
    return 0;
}

Java

// Converting Head Recursion into Loop
import java.util.*;
class GFG
{
// Recursive function
static void fun(int n)
{
    int i = 1;
    while (i <= n) {
        System.out.print(" "+ i);
        i++;
    }
}
 
// Driver code
public static void main(String[] args)
{
    int x = 3;
    fun(x);
}
}
 
// this code is contributed by shivanisinghss2110

Python3

# Converting Head Recursion into Loop
# Recursive function
def fun(n):
 
    i = 1
    while (i <= n):
        print(i,end=" ")
        i+=1
     
# Driver code
x = 3
fun(x)
 
# This code is contributed by shivanisinghss2110

C#

// Converting Head Recursion into Loop
using System;
class GFG
{
// Recursive function
static void fun(int n)
{
    int i = 1;
    while (i <= n) {
        Console.Write(" "+ i);
        i++;
    }
}
 
// Driver code
public static void Main(String[] args)
{
    int x = 3;
    fun(x);
}
}
 
// this code is contributed by shivanisinghss2110

Javascript

<script>
 
// Converting Head Recursion into Loop
// Recursive function
function fun(n)
{
    var i = 1;
    while (i <= n) {
        document.write(" "+ i);
        i++;
    }
}
 
// Driver code
var x = 3;
fun(x);
 
// this code is contributed by shivanisinghss2110
 
</script>
Producción

 1 2 3
  • Tree Recursion : Para entender Tree Recursion , primero entendamos Linear Recursion . Si una función recursiva se llama a sí misma por una vez, se conoce como recursividad lineal . De lo contrario, si una función recursiva se llama a sí misma más de una vez, se conoce como Tree Recursion .
    Ejemplo:
    Pseudo Código para recursividad lineal
fun(n)
{
    // some code
    if(n>0)
    {
        fun(n-1); // Calling itself only once
    }
    // some code
}

Programa para la recursividad del árbol

C++

// C++ program to show Tree Recursion
#include <iostream>
using namespace std;
 
// Recursive function
void fun(int n)
{
    if (n > 0)
    {
        cout << " " << n;
         
        // Calling once
        fun(n - 1);
         
        // Calling twice
        fun(n - 1);
    }
}
 
// Driver code
int main()
{
    fun(3);
    return 0;
}
 
// This code is contributed by shivanisinghss2110

C

// C program to show Tree Recursion
 
#include <stdio.h>
 
// Recursive function
void fun(int n)
{
    if (n > 0) {
        printf("%d ", n);
 
        // Calling once
        fun(n - 1);
 
        // Calling twice
        fun(n - 1);
    }
}
 
// Driver code
int main()
{
    fun(3);
    return 0;
}

Java

// Java program to show Tree Recursion
class GFG
{
   
// Recursive function
static void fun(int n)
{
    if (n > 0) {
        System.out.print(" "+ n);
 
        // Calling once
        fun(n - 1);
 
        // Calling twice
        fun(n - 1);
    }
}
 
// Driver code
public static void main(String[] args)
  {
       
    fun(3);
    }
}
 
// This code is contributed by shivanisinghss2110

Python3

# C++ program to show Tree Recursion
# Recursive function
def fun(n):
 
    if (n > 0):
     
        print(n, end=" ")
         
        # Calling once
        fun(n - 1)
         
        # Calling twice
        fun(n - 1)
     
 
 
# Driver code
fun(3)
 
# This code is contributed by shivanisinghss2110

C#

// C# program to show Tree Recursion
using System;
class GFG
{
   
// Recursive function
static void fun(int n)
{
    if (n > 0) {
        Console.Write(" "+ n);
 
        // Calling once
        fun(n - 1);
 
        // Calling twice
        fun(n - 1);
    }
}
 
// Driver code
public static void Main(String[] args)
  {
       
    fun(3);
    }
}
 
// This code is contributed by shivanisinghss2110

Javascript

<script>
 
// JavaScript program to show Tree Recursion
 
// Recursive function
function fun(n)
{
    if (n > 0) {
        document.write(" "+ n);
 
        // Calling once
        fun(n - 1);
 
        // Calling twice
        fun(n - 1);
    }
}
 
// Driver code
    fun(3);
 
// This code is contributed by shivanisinghss2110
 
</script>
Producción

 3 2 1 1 2 1 1

Entendamos el ejemplo rastreando el árbol de la función recursiva. Así es como se hacen las llamadas y así se producen las salidas.

Complejidad de tiempo para recursión de árbol: O(2^n)  
Complejidad de espacio para recursión de árbol: O(n)
Nota: Complejidad de tiempo y espacio se proporciona para este ejemplo específico. Puede variar para otro ejemplo.

  • Recursión anidada : en esta recursión, una función recursiva pasará el parámetro como una llamada recursiva. Eso significa «recursión dentro de la recursión». Veamos el ejemplo para entender esta recursividad.
    Ejemplo:

C++

// C++ program to show Nested Recursion
#include <iostream>
using namespace std;
 
int fun(int n)
{
    if (n > 100)
        return n - 10;
 
    // A recursive function passing parameter
    // as a recursive call or recursion inside
    // the recursion
    return fun(fun(n + 11));
}
 
// Driver code
int main()
{
    int r;
    r = fun(95);
   
    cout << " " << r;
   
    return 0;
}
 
// This code is contributed by shivanisinghss2110

C

// C program to show Nested Recursion
 
#include <stdio.h>
int fun(int n)
{
    if (n > 100)
        return n - 10;
 
    // A recursive function passing parameter
    // as a recursive call or recursion
    // inside the recursion
    return fun(fun(n + 11));
}
 
// Driver code
int main()
{
    int r;
    r = fun(95);
    printf("%d\n", r);
    return 0;
}

Java

// Java program to show Nested Recursion
import java.util.*;
 
class GFG {
static int fun(int n)
{
    if (n > 100)
        return n - 10;
 
    // A recursive function passing parameter
    // as a recursive call or recursion
    // inside the recursion
    return fun(fun(n + 11));
}
 
// Driver code
public static void main(String args[])
{
    int r;
    r = fun(95);
    System.out.print("  "+ r);
     
}
}
// This code is contributed by shivanisinghss2110

Python3

# Python program to show Nested Recursion
def fun(n):
 
    if (n > 100):
        return n - 10
 
    # A recursive function passing parameter
    # as a recursive call or recursion inside
    # the recursion
    return fun(fun(n + 11))
 
# Driver code
r = fun(95)
print("", r)
 
# This code is contributed by shivanisinghss2110

C#

// C# program to show Nested Recursion
using System;
 
class GFG {
static int fun(int n)
{
    if (n > 100)
        return n - 10;
 
    // A recursive function passing parameter
    // as a recursive call or recursion
    // inside the recursion
    return fun(fun(n + 11));
}
 
// Driver code
public static void Main(String []args)
{
    int r;
    r = fun(95);
    Console.Write("  "+ r);
     
}
}
// This code is contributed by shivanisinghss2110

Javascript

<script>
 
// JavaScript program to show Nested Recursion
function fun( n)
{
    if (n > 100)
        return n - 10;
 
    // A recursive function passing parameter
    // as a recursive call or recursion
    // inside the recursion
    return fun(fun(n + 11));
}
 
// Driver code
    var r;
    r = fun(95);
    document.write("  "+ r);
     
// This code is contributed by shivanisinghss2110
</script>
Producción

 91

Entendamos el ejemplo rastreando el árbol de la función recursiva. Así es como se hacen las llamadas y así se producen las salidas.

2. Recursión indirecta : en esta recursión, puede haber más de una función y se llaman entre sí de manera circular.

Del diagrama anterior, diversión (A) está llamando a la diversión (B), diversión (B) está llamando a la diversión (C) y diversión (C) está llamando a la diversión (A) y, por lo tanto, hace un ciclo.

Ejemplo:

C++

// C++ program to show Indirect Recursion
#include <iostream>
using namespace std;
 
void funB(int n);
 
void funA(int n)
{
    if (n > 0) {
        cout <<" "<< n;
 
        // fun(A) is calling fun(B)
        funB(n - 1);
    }
}
 
void funB(int n)
{
    if (n > 1) {
        cout <<" "<< n;
 
        // fun(B) is calling fun(A)
        funA(n / 2);
    }
}
 
// Driver code
int main()
{
    funA(20);
    return 0;
}
 
// this code is contributed by shivanisinghss2110

C

// C program to show Indirect Recursion
 
#include <stdio.h>
 
void funB(int n);
 
void funA(int n)
{
    if (n > 0) {
        printf("%d ", n);
 
        // Fun(A) is calling fun(B)
        funB(n - 1);
    }
}
 
void funB(int n)
{
    if (n > 1) {
        printf("%d ", n);
 
        // Fun(B) is calling fun(A)
        funA(n / 2);
    }
}
 
// Driver code
int main()
{
    funA(20);
    return 0;
}

Java

// Java program to show Indirect Recursion
import java.io.*;
 
class GFG{
 
static void funA(int n)
{
    if (n > 0) {
        System.out.print(" " +n);
 
        // Fun(A) is calling fun(B)
        funB(n - 1);
    }
}
 
static void funB(int n)
{
    if (n > 1) {
        System.out.print(" "  +n);
 
        // Fun(B) is calling fun(A)
        funA(n / 2);
    }
}
 
// Driver code
public static void main (String[] args)
{
    funA(20);
}
}
 
// This code is contributed by shivanisinghss2110

C#

// C# program to show Indirect Recursion
using System;
 
class GFG{
 
static void funA(int n)
{
    if (n > 0) {
        Console.Write(" " +n);
 
        // Fun(A) is calling fun(B)
        funB(n - 1);
    }
}
 
static void funB(int n)
{
    if (n > 1) {
        Console.Write(" "  +n);
 
        // Fun(B) is calling fun(A)
        funA(n / 2);
    }
}
 
// Driver code
public static void Main (String[] args)
{
    funA(20);
}
}
 
// This code is contributed by shivanisinghss2110

Python3

# Python program to show Indirect Recursion
def funA(n):
    if (n > 0):
        print("", n, end='')
         
        # Fun(A) is calling fun(B)
        funB(n - 1)
     
def funB( n):
    if (n > 1):
        print("", n, end='')
         
        # Fun(B) is calling fun(A)
        funA(n // 2)
         
# Driver code
funA(20)
 
 
# This code is contributed by shivanisinghss2110

Javascript

<script>
 
// JavaScript program to show Indirect Recursion
function funA(n)
{
    if (n > 0) {
        document.write(n.toFixed(0) + "</br>");
 
        // Fun(A) is calling fun(B)
        funB(n - 1);
    }
}
 
function funB(n)
{
    if (n > 1) {
        document.write(n.toFixed(0) + "</br>");
 
        // Fun(B) is calling fun(A)
        funA(n / 2);
    }
}
 
// Driver code
funA(20);
 
// this code is contributed by shivanisinghss2110
</script>
Producción

 20 19 9 8 4 3 1

Entendamos el ejemplo rastreando el árbol de la función recursiva. Así es como se hacen las llamadas y así se producen las salidas.

Este artículo es una contribución de AmiyaRanjanRout . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando write.geeksforgeeks.org o enviar su artículo por correo a review-team@geeksforgeeks.org. Vea su artículo en la página principal de GeeksforGeeks y ayude a otros Geeks.
 

Publicación traducida automáticamente

Artículo escrito por AmiyaRanjanRout y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *