lunes, 31 de octubre de 2011

RECURSIVIDAD

DEFINICION.- Se utiliza para realizar una llamada a una funcion desde la misma funcion.
Como ejemplo útil se puede presentar el calculo de números factoriales. Él factorial de 0 es, por definición, 1. Los factoriales de números mayores se calculan mediante la multiplicación de 1 * 2 * …, incrementando el número de 1 en 1 hasta llegar al número para el que se está calculando el factorial. 

Para entender mejor lo que en realidad es el concepto de recursión veamos un poco lo referente a la secuencia de Fibonacci.
Principalmente habría que aclarar que es un ejemplo menos familiar que el del factorial, que consiste en la secuencia de enteros.
0,1,1,2,3,5,8,13,21,34,...,
Cada elemento en esta secuencia es la suma de los precedentes (por ejemplo 0 + 1 = 0, 1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, ...) sean fib(0) = 0, fib (1) = 1 y así sucesivamente, entonces puede definirse la secuencia de Fibonacci mediante la definición recursiva (define un objeto en términos de un caso mas simple de si mismo):
fib (n) = n if n = = 0 or n = = 1
fib (n) = fib (n - 2) + fib (n - 1) if n >= 2
Por ejemplo, para calcular fib (6), puede aplicarse la definición de manera recursiva para obtener:
Fib (6) = fib (4) + fib (5) = fib (2) + fib (3) + fib (5) = fib (0) + fib (1) + fib (3) + fib (5) = 0 + 1 fib (3) + fib (5)
  1. + fib (1) + fib (2) + fib(5) =
  1. + 1 + fib(0) + fib (1) + fib (5) =
  2. + 0 + 1 + fib(5) = 3 + fib (3) + fib (4) = 3 + 1 + fib (0) + fib (1) + fib (4) =
  3. + fib (1) + fib (2) + fib (4) =
  4. + 0 + 1 + fib (2) + fib (3) = 5 + fib (0) + fib (1) + fib (3) =
  5. + 0 + 1 + fib (1) + fib (2) = 6 + 1 + fib (0) + fib (1) =
  6. + 0 + 1 = 8
Obsérvese que la definición recursiva de los números de Fibonacci difiere de las definiciones recursivas de la función factorial y de la multiplicación . La definición recursiva de fib se refiere dos veces a sí misma . Por ejemplo, fib (6) = fib (4) + fib (5), de tal manera que al calcular fib (6), fib tiene que aplicarse de manera recursiva dos veces. Sin embargo calcular fib (5) también implica calcular fib (4), así que al aplicar la definición hay mucha redundancia de cálculo. En ejemplo anterior, fib(3) se calcula tres veces por separado. Sería mucho mas eficiente "recordar" el valor de fib(3) la primera vez que se calcula y volver a usarlo cada vez que se necesite. Es mucho mas eficiente un método iterativo como el que sigue parar calcular fib (n).
If (n < = 1)
return (n);
lofib = 0 ;
hifib = 1 ;
for (i = 2; i < = n; i ++)
{
x = lofib ;
lofib = hifib ;
hifib = x + lofib ;
} /* fin del for*/
return (hifib) ;
Compárese el numero de adiciones (sin incluir los incrementos de la variable índice, i) que se ejecutan para calcular fib (6) mediante este algoritmo al usar la definición recursiva. En el caso de la función factorial, tienen que ejecutarse el mismo numero de multiplicaciones para calcular n! Mediante ambos métodos: recursivo e iterativo. Lo mismo ocurre con el numero de sumas en los dos métodos al calcular la multiplicación. Sin embargo, en el caso de los números de Fibonacci, el método recursivo es mucho mas costoso que el iterativo.

Cadenas recursivas:


Una función recursiva no necesita llamarse a sí misma de manera directa. En su lugar, puede hacerlo de manera indirecta como en el siguiente ejemplo:
a (formal parameters) b (formal parameters)
{ {
. .
b (arguments); a (arguments);
. .
} /*fin de a*/ } /*fin de b*/
En este ejemplo la función a llama a b, la cual puede a su vez llamar a a, que puede llamar de nuevo a b. Así, ambas funciones a y b, son recursivas, dado que se llamas a sí mismo de manera indirecta. Sin embargo, el que lo sean no es obvio a partir del examen del cuerpo de una de las rutinas en forma individual. La rutina a, parece llamar a otra rutina b y es imposible determinar que se puede llamar así misma de manera indirecta al examinar sólo a a.
Pueden incluirse mas de dos rutinas en una cadena recursiva. Así, una rutina a puede llamar a b, que llama a c, ..., que llama a z, que llama a a. Cada rutina de la cadena puede potencialmente llamarse a sí misma y, por lo tanto es recursiva.

APLICACIONES
uno de los ejemplos de recursividad es el juego muy conocido de LAS TORRES DE HANOI:
 
//********************************************************************
// hanoi.java
// aporte de @ohk
// para elhacker.net
//********************************************************************
 
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
 
//********************************************************************
 
public class hanoi extends Applet implements Runnable
{
    Graphics g;
 
    static public Image fondo;
 
    static public int ancho;
    static public int alto;
 
    static public int demora = 200;
 
    private boolean imagen_cargada = false;
 
    private int total_discos = 3;
 
    private Thread mi_hilo;
 
    private boolean hilo_iniciado = false;
 
    private Label label;
 
    private TextField resultado;
 
    String salida = "";
    int contador = 0;
 
    torre t [];
 
    int torre_origen = 0;
    int torre_destino = 2;
 
    //----------------------------------------------------------------
 
    public void init ()
    {
 
 label = new Label ("Comportamiento de las Torres de Hanoi");
 label.setFont (new java.awt.Font ("Georgia Ref", java.awt.Font.BOLD, 20));
 
 resultado = new TextField (40);
 resultado.setFont (new java.awt.Font ("Georgia Ref", java.awt.Font.BOLD, 15));
 //Container contString = getContentPane ();
 //contString.setLayout (new FlowLayout ());
 resultado.setEnabled (false);
 //contString.add (new ScrollPane (resultado));
 
 g = getGraphics ();
 
 String parametro;
 
 parametro = getParameter ("TOTAL");
 if (parametro != null)
     total_discos = Integer.parseInt (parametro);
 
 parametro = getParameter ("DEMORA");
 if (parametro != null)
     demora = Integer.parseInt (parametro);
 
 ancho = size ().width;
 alto = size ().height;
 
 fondo = getImage (getCodeBase (), "egipto.gif");
 
 Image imagenFueraPant = createImage (ancho, alto);
 Graphics CGFueraPant = imagenFueraPant.getGraphics ();
 CGFueraPant.drawImage (fondo, 0, 0, this);
 
 t = new torre [3];
 
 t [0] = new torre (g);
 t [1] = new torre (g);
 t [2] = new torre (g);
 
 for (int i = 0 ; i < total_discos ; i++)
 {
     t [0].agregar (i);
 }
 add (label);
 add (resultado);
 
    }
 
 
    //----------------------------------------------------------------
 
    public boolean imageUpdate (Image img, int infoflags, int x, int y,
     int ancho, int alto)
    {
 if (infoflags == ALLBITS)
 {
     imagen_cargada = true;
     repaint ();
     return false;
 }
 else
     return true;
    }
 
 
    //----------------------------------------------------------------
 
    public void paint (Graphics g)
    {
 if (!imagen_cargada)
     showStatus ("Torre de Hanoi:  cargando imagen");
 
 else
 {
     if (hilo_iniciado)
  if (mi_hilo.isAlive ())
      showStatus ("Torres de Hanoi:  Corriendo");
  else
      showStatus ("Torres de Hanoi:  Haga clic otra vez para reiniciar");
     else
  showStatus ("Torres de Hanoi:  Haga clic para iniciar");
 
     ancho = size ().width;
     alto = size ().height;
 
     g.drawImage (fondo, 0, 0, ancho, alto, this);
 
     int x_inc = ancho / 10;
 
     t [0].paint (x_inc * 1, x_inc * 2, alto);
     t [1].paint (x_inc * 4, x_inc * 2, alto);
     t [2].paint (x_inc * 7, x_inc * 2, alto);
 }
    }
 
 
    //----------------------------------------------------------------
 
    public boolean mouseDown (Event evt, int x, int y)
    {
 if (!hilo_iniciado || !mi_hilo.isAlive ())
 {
     mi_hilo = new Thread (this);
     mi_hilo.start ();
     showStatus ("Torre de Hanoi:  Corriendo");
     hilo_iniciado = true;
     resuelve_hanoi (total_discos, torre_origen + 1, torre_destino + 1);
 
 
 }
 
 return true;
    }
 
 
    //----------------------------------------------------------------
 
    public void run ()
    {
 mover_torre (total_discos, torre_origen, torre_destino, 1);
 
 int temp = torre_destino;
 torre_destino = torre_origen;
 torre_origen = temp;
 
 showStatus ("Torre de Hanoi:  Haga clic otra vez para reiniciar");
    }
 
 
    //----------------------------------------------------------------
 
    private void mover_torre (int discos, int origen, int destino, int temporal)
    {
 if (discos > 0)
 {
     mover_torre (discos - 1, origen, temporal, destino);
     mover_disco (origen, destino);
     mover_torre (discos - 1, temporal, destino, origen);
 }
    }
 
 
    //----------------------------------------------------------------
 
    private void mover_disco (int origen, int destino)
    {
 int disco = t [origen].pop ();
 t [destino].push (disco);
    }
 
    public void resuelve_hanoi (int n, int inicial, int finalizar)
    {
 int libre = 0;
 if (n == 1)
 {
     resultado.setText (" Mover disco superior de la torre " + inicial + " a la torre " + finalizar);
 }
 else
 {
 
     //Determinar cual es la aguja libre
     if (inicial != 1 && finalizar != 1)
  libre = 1;
     else if (inicial != 2 && finalizar != 2)
     {
  libre = 2;
     }
     else
  libre = 3;
 
     //Primer subproblema:mover n-1 discos de inicial a libre
     resuelve_hanoi (n - 1, inicial, libre);
     //Transferir el disco grande a su posicion final
     try
     {
  Thread.sleep (3200);
     }
     catch (InterruptedException e)
     {
 
     }
     ;
     resultado.setText (" Mover disco superior de la torre " + inicial + " a la torre " + finalizar);
     try
     {
  Thread.sleep (3200);
     }
     catch (InterruptedException e)
     {
 
     }
     ;
     //Segundo subproblema: mover n-1 discos de libre a final
     resuelve_hanoi (n - 1, libre, finalizar);
 }
    }
}
 







COLAS

DEFINICION.-es una estructura de datos, caracterizada por ser una secuencia de elementos en la que la operación de inserción push se realiza por un extremo y la operación de extracción pop por el otro. También se le llama estructura FIFO (del inglés First In First Out), debido a que el primer elemento en entrar será también el primero en salir.
Las colas se utilizan en sistemas informáticos, transportes y operaciones de investigación (entre otros), dónde los objetos, personas o eventos son tomados como datos que se almacenan y se guardan mediante colas para su posterior procesamiento. Este tipo de estructura de datos abstracta se implementa en lenguajes orientados a objetos mediante clases, en forma de listas enlazadas.

APLICACION DE LAS COLAS

La particularidad de una estructura de datos de cola es el hecho de que sólo podemos acceder al primer y al último elemento de la estructura. Así mismo, los elementos sólo se pueden eliminar por el principio y sólo se pueden añadir por el final de la cola.
Ejemplo de Cola
Ejemplos de colas en la vida real serían: personas comprando en un supermercado, esperando para entrar a ver un partido de béisbol, esperando en el cine para ver una película, una pequeña peluquería, etc. La idea esencial es que son todos líneas de espera.

 En caso de estar vacía borrar un elemento sería imposible hasta que no se añade un nuevo elemento. A la hora de añadir un elemento podríamos darle una mayor importancia a unos elementos que a otros (un cargo VIP) y para ello se crea un tipo de cola especial que es la cola de prioridad

OPERACIONES CON COLAS

  • Crear: se crea la cola vacía.
  • Encolar (añadir, entrar, insertar): se añade un elemento a la cola. Se añade al final de esta.
  • Desencolar (sacar, salir, eliminar): se elimina el elemento frontal de la cola, es decir, el primer elemento que entró.
  • Frente (consultar, front): se devuelve el elemento frontal de la cola, es decir, el primer elemento que entró. 
TIPOS DE COLAS


La ColaNV es la cola no vacía, que diferenciamos de la cola normal a la hora de tomar en cuenta errores. A su vez, el elemento X representa el tipo de valor que puede contener la cola: entero, carácter, registro....

public void inserta(Elemento x) {
        Nodo Nuevo;
        Nuevo = new Nodo(x, null);
        if (NodoCabeza == null) {
            NodoCabeza = Nuevo;
        } else {
            NodoFinal.Siguiente = Nuevo;
        }
        NodoFinal = Nuevo;
    }
 
    public Elemento cabeza() throws IllegalArgumentException {
        if (NodoCabeza == null) {
            throw new IllegalArgumentException();
        } else {
            return NodoCabeza.Info;
        }
    }
 
    public Cola() {
    // Devuelve una Cola vacía
        NodoCabeza = null;
        NodoFinal = null;
    }

domingo, 16 de octubre de 2011

PILA

(stack en inglés) es una lista ordinal o estructura de datos en la que el modo de acceso a sus elementos es de tipo LIFO (del inglés Last In First Out, último en entrar, primero en salir) que permite almacenar y recuperar datos. Esta estructura se aplica en multitud de ocasiones en el área de informática debido a su simplicidad y ordenación implícita de la propia estructura.
Representación gráfica de una pila
Para el manejo de los datos se cuenta con dos operaciones básicas: apilar (push), que coloca un objeto en la pila, y su operación inversa, retirar (o desapilar, pop), que retira el último elemento apilado.
En cada momento sólo se tiene acceso a la parte superior de la pila, es decir, al último objeto apilado (denominado TOS, Top of Stack en inglés). La operación retirar permite la obtención de este elemento, que es retirado de la pila permitiendo el acceso al siguiente (apilado con anterioridad), que pasa a ser el nuevo TOS.
Por analogía con objetos cotidianos, una operación apilar equivaldría a colocar un plato sobre una pila de platos, y una operación retirar a retirarlo

APLICACIONES DE PILAS
  • llamadas a subprogramas.
  • recursividad
  • conversion de expresiones aritmeticas


TIPOS DE PILAS
  • Pila estatica
  • Pila dinamica


OPERACIONES CON PILAS

Una pila cuenta con 2 operaciones imprescindibles: apilar y desapilar, a las que en las implementaciones modernas de las pilas se suelen añadir más de uso habitual.
  • Crear: se crea la pila vacía.
  • Apilar: se añade un elemento a la pila.(push)
  • Desapilar: se elimina el elemento frontal de la pila.(pop)
  • Cima: devuelve el elemento que esta en la cima de la pila. (top o peek)
  • Vacía: devuelve cierto si la pila está vacía o falso en caso contrario.