4.1.2.3 Ejemplo de Aplicación 04

 

EJEMPLO DE APLICACIÓN

 

Ejemplo de uso: eliminación de recursividad

Suponga que una función F realiza un llamado recursivo dentro de su código, lo que se ilustra en la siguiente figura:

Si la llamada recursiva es lo último que hace la función F, entonces dicha llamada se puede substituir por un ciclo while. Este caso es conocido como tail recursion y en lo posible hay que evitarlo en la programación, ya que cada llamada recursiva ocupa espacio en la memoria del computador, y en el caso del tail recursion es muy simple eliminarla. Por ejemplo:

void imprimir(int[] a, int j) // versión recursiva

{

  if (j<a.length)

  {

    System.out.println(a[j]);

    imprimir(a, j+1); // tail recursion

  }

}

 

void imprimir(int[] a, int j) // versión iterativa

{

  while (j<a.length)

  {

    System.out.println(a[j]);

    j=j+1;

  }

}

En el caso general, cuando el llamado recursivo se realiza en medio de la función F, la recursión se puede eliminar utilizando una pila.

Por ejemplo: recorrido en preorden de un arbol binario.

// "raiz" es la referencia a la raiz del arbol

// llamado inicial: preorden(raiz)

 

// version recursiva

 

void preorden(Nodo nodo)

{

  if (nodo!=null)

  {

    System.out.print(nodo.elemento);

    preorden(nodo.izq);

    preorden(nodo.der);

  }

}

 

// primera version iterativa

 

void preorden(Nodo nodo)

{

  Nodo aux;

  Pila pila=new Pila(); // pila de nodos

  pila.apilar(nodo);

  while(!pila.estaVacia()) // mientras la pila no este vacia

  {

    aux=pila.desapilar();

    if (aux!=null)

    {

      System.out.print(aux.elemento);

      // primero se apila el nodo derecho y luego el izquierdo

      // para mantener el orden correcto del recorrido

      // al desapilar los nodos

      pila.apilar(aux.der);

      pila.apilar(aux.izq);

    }

  }

}

 

// segunda version iterativa

// dado que siempre el ultimo nodo apilado dentro del bloque if es

// aux.izq podemos asignarlo directamente a aux hasta que éste sea

// null, es decir, el bloque if se convierte en un bloque while

// y se cambia el segundo apilar por una asignacion de la referencia

 

void preorden(Nodo nodo)

{

  Nodo aux;

  Pila pila=new Pila(); // pila de nodos

  pila.apilar(nodo);

  while(!pila.estaVacia()) // mientras la pila no este vacia

  {

    aux=pila.desapilar();

    while (aux!=null)

    {

      System.out.print(aux.elemento);

      pila.apilar(aux.der);

      aux=aux.izq;

    }

  }

}

Si bien los programas no recursivos son más eficientes que los recursivos, la eliminación de recursividad (excepto en el caso de tail recursion) le quita claridad al código del programa. Por lo tanto: