miércoles, 18 de noviembre de 2015

Pilas en Java




Una pila (stack) es una colección ordenada de elementos a los que sólo se puede acceder por un único lugar o extremo de la pila.  Al primer elemento agregado se lo denomina como "fondo", mientras que al último se lo conoce como "cima". Los elementos de la pila se añaden o se borran de la misma sólo por su parte superior (cima).

Debido a su propiedad específica “último en entrar, primero en salir ” se conoce a las pilas como
estructura de datos LIFO (last-in / first-out). 

A continuación se muestra un vídeo explicativo sobre las Pilas en Java:




Una pila se puede implementar de las siguientes formas:
  1. Guardando los elementos en un arreglo en cuyo caso su dimensión o longitud es fija. 
  2. Utilizando un vector para almacenar los elementos. 
  3. Construir una lista enlazada, cada elemento de la pila forma un nodo de la lista; la lista crece o decrece según se añaden o se extraen, respectivamente, elementos de la pila; ésta es una representación dinámica y no existe limitación en su tamaño excepto la memoria de la computadora.

Operaciones de las Pilas:

Una pila cuenta con 2 operaciones imprescindibles:

Apilar (push): Consiste en añadir un elemento a la pila. En la siguiente imagen se explica de una forma más abstracta en la que se puede ver que se está añadiendo el dato "7" sobre el dato "8", convirtiéndose éste en la "cima" de la pila.

 Desapilar (pop): Es la operación contraria de "apilar", es decir, en lugar de añadir elementos a la pila, se los va a quitar de la misma. En la siguiente imagen se explica de una forma más abstracta en la que se puede ver que se está quitando de la pila el dato "7" establecido anteriormente como la "cima".

Después de las dos operaciones fundamentales en una pila, se pueden establecer otras, las cuales servirán para obtener información y manipular su contenido:

CrearPila: Inicia la pila
Pila vacía (Empty): Comprueba si la pila no tiene elementos
Pila llena: Comprueba si la pila está llena de elementos
Limpiar pila: Quita todos sus elementos y deja la pila vacía
CimaPila (Peek): Obtiene el elemento cima de la pila
Tamaño de la pila: Número de elementos máximo que puede contener la pila
Buscar (Search): Busca un elemento determinado que esté dentro de la pila y devuelve su posición.

En resumen...

Una pila es una estructura de datos del tipo LIFO, con dos operaciones imprescindibles: apilar (push) y desapilar (pop), al primer elemento se lo conoce como "fondo" y al último como "cima". 



Ejemplo práctico:

A continuación se muestra un programa simple, en donde se aplican las operaciones apilar y desapilar elementos en una Pila. El programa consiste en un arreglo de 10 números (del 9 - 0) enteros que, mediante la funcion "push" agrega los mismos a la pila. Y mediante la función "pop" elimina 5 elementos de la pila. Mostrando únicamente los números del 9 al 5

Clase Pilas:

public class Pilas 
{

    private int stck[];
    private int tos;
 
    //Constructor
    Pilas(int size)
    {
        //Crear la pila
        stck = new int[size];
        tos = -1;
    }
 
    //Introduce valor en la pila
    void push(int value) 
    {
        if (tos == stck.length - 1)
            System.out.println("Stack Overflow!");
            //Pila esta llena
        else
            stck[++tos] = value;
            //Almacena valor en pila
    }
 
    //Retira valor de la pila
    int pop() 
    {
        if (tos < 0) 
        {
            //La pila esta vacia
            System.out.println("Stack Underflow!");
            return 0;
        } else
            return stck[tos--];
 
    }
 
}
Clase Principal:


public class Principal {

 public static void main(String[] args) 
 {
  System.out.println("EJERCICIO BÁSICO PILAS EN JAVA");
   
        Pilas pila = new Pilas(10);
        //Llenar la pila
        for (int i = 0; i < 10; i++) pila.push(i);
        //Retirar 5 primeros elementos de la pila
        System.out.println("Valores contenidos en la pila: ");
        for (int i = 0; i < 5; i++) System.out.println("\t " + pila.pop());

 }

}

Captura de pantalla del programa:



Referencias:


Academia. (2015). “Listas, pilas y colas en Java”. Recuperado el 18 de noviembre del 2015 de: http://www.academia.edu/9865829/Listas_pilas_y_colas_en_Java

Colas en Java


Una cola es una estructura de datos que almacena elementos en una lista y permite acceder a los datos por uno de los dos extremos de la lista. Un elemento se inserta en la cola (parte final) de la lista y se suprime o elimina por el frente (parte inicial, frente) de la lista. Las aplicaciones utilizan una cola para almacenar elementos en su orden de aparición o concurrencia.

Los elementos se eliminan de la cola en el mismo orden en que se almacena, por ello una cola es una estructura de tipo FIFO (first-in/first-out) es decir que el dato primero en entrar será el primero en salir.



A continuación se muestra un vídeo explicativo sobre las Colas en Java:


Al igual que las pilas, las colas se pueden implementar utilizando una estructura estática (arreglos), o una estructura dinámica (listas enlazadas, vectores, etc). 

Operaciones de las Colas:

Al igual que las Pilas, las colas poseen dos operaciones imprescindibles que son para añadir elementos o "encolar" y para eliminar elementos o "desencolar", al igual que poseen operaciones para manipular y mostrar su contenido, las cuales son:

CrearCola: Inicia la cola como vacía
Cola vacía: Comprobar si la cola no tiene elementos
Cola llena: Comprobar si la cola está llena de elementos
Frente: Obtiene el elemento frente o primero de la cola
Tamaño de la cola: Número de elementos máximo que puede contener la cola

En resumen...

Una cola es una estructura de datos del tipo FIFO, con dos operaciones imprescindibles: encolar y desencolar, al primer elemento se lo conoce como "frente o principio" y al último como "final".




Ejemplo práctico:

A continuación se muestra un programa simple, en donde se aplican las operaciones encolar y desencolar elementos en una Cola. El programa está hecho con listas simples enlazadas en el cual se insertan 5 elementos, utilizando la función insertar (encolar). Después se utiliza la función extraer (encolar) para eliminar el primer nodo. Finalmente se cuenta cuantos elementos tiene la nueva lista, e imprime los valores.

 Clase Nodo:

public class Nodo 
{
 //Declaracion de atributos
 private int dato;
 private Nodo next;
 
 //Constructor
 public Nodo(int dato){
 this.dato=dato;
 }
 
 //Metodos getter and setters
 public int getDato() 
 {
 return dato;
 }
 public void setDato(int dato) 
 {
 this.dato = dato;
 }
 public Nodo getNext() 
 {
 return next;
 }
 public void setNext(Nodo next) 
 {
 this.next = next;
 }
 
 //Metodo toString
 public String toString()
 {
 String s=" "+dato+" ";
 return s;
 }
}


Clase Colas:

public class Colas 
{
 //Declaración de atributos
 private Nodo inicio;
 private Nodo termino;

 //Constructor sin parametros
 public Colas()
 {
 inicio=null;
 termino=null;
 }
 
 //Metodo insertar
 public void insertar(int dato)
 {
 Nodo i=new Nodo(dato);
 i.setNext(null);
 if(inicio==null & termino==null)
 {
 inicio=i;
 termino=i;
 }
 termino.setNext(i);
 termino=termino.getNext();
 }
 
 //Metodo extraer dato
 public int extraer()
 {
 int dato=inicio.getDato();
 inicio=inicio.getNext();
 return dato;
 }
 
 //Metodo para comprobar que la cola no esta vacia
 public boolean estaVacia()
 {
 boolean cola=false;
 if(inicio==null & termino==null)
 {
 cola=true;
 System.out.println("La cola esta vacia");
 }
 else
 {
 System.out.println("La cola no esta vacia");
 cola=false;
 }
 return cola;
 }
 
 //Metodo para contar los elementos de la cola
 public int contar()
 {
 int contador=0;
 Nodo c=this.inicio;
 while(c!=null)
 {
 contador++;
 c=c.getNext();
 }
 System.out.println("Numero de datos en la cola: "+contador);
 return contador;
 }
 
 //Metodo toString
 public String toString()
 {
 Nodo c=this.inicio;
 String s="";
 while(c!=null)
 {
 s=s+c.toString();
 c=c.getNext();
 }
 return s;
 } 
}



Clase Principal:


public class Principal 
{
 public static void main(String[] args) 
 {
  Colas cola1=new Colas();
  cola1.insertar(46);
  cola1.insertar(12);
  cola1.insertar(87);
  cola1.insertar(125);
  cola1.insertar(30);
  cola1.extraer();
  cola1.estaVacia();
  cola1.contar();
  System.out.println(cola1.toString());
 }
}


Captura de pantalla del programa:



Referencias:

Academia. (2015). “Listas, pilas y colas en Java”. Recuperado el 18 de noviembre del 2015 de: http://www.academia.edu/9865829/Listas_pilas_y_colas_en_Java

Comparación entre Pilas y Colas en Java

La principal diferencia entre una Pila y una Cola en java consiste en su modelo de entrada y salida, es decir, una Pila tiene un modelo LIFO (last-in / first-out), el cual quiere decir que el último elemento en entrar a la Pila será el primero en salir. En cambio, una cola tiene un modelo FIFO (first-in / first-out), el cual quiere decir que el primer elemento en entrar, será el primer elemento en salir. Esta comparación se explica mejor en la siguiente imagen:


Otra diferencia entre una pila y una cola, como se puede ver en la imagen, es que en una pila los elementos se agregan y se eliminan en el mismo extremo. En cambio, en una cola los elementos se agregan de un extremo de la cola llamado "final", y se eliminan del otro extremo de la cola llamado "frente".

             

A continuación se muestra un vídeo explicativo sobre la comparación entre Pilas y colas en Java:




Referencias:


Academia. (2015). “Listas, pilas y colas en Java”. Recuperado el 18 de noviembre del 2015 de: http://www.academia.edu/9865829/Listas_pilas_y_colas_en_Java

Ejercicio 3 - Listas simples enlazadas

Enunciado:


Escribir un programa que realice las siguientes tareas:
  • Crear una lista enlazada de números enteros positivos al alzar, donde la inserción se realiza por el último nodo.
  • Recorrer la lista para mostrar los elementos por pantalla.
  • Eliminar todos los nodos que superen un valor dado.

Para realizar este ejercicio, al igual que los dos ejercicios anteriores se debe tener en cuenta las definiciones para crear nodos, y los metodos principales para agregar un inicio a la lista, agregar un fin a la lista, y eliminar un nodo de la lista, el método que elimina los números que superen un límite es similar al método estandar para eliminar nodos.

A continuación se muestra el código:

Clase Nodo:



public class Nodo {
 
 //Declaración de atributos
 private int dato;
 private Nodo siguiente;
 
 //Constructores de la clase Nodo
 public Nodo (int dato, Nodo siguiente)
 {
  this.dato=dato;
  
  this.siguiente=siguiente;
 }
 
 public Nodo (int datos)
 {
  this.dato=datos;
  this.siguiente=null;
 }
 
 //Metodos getter and setter
 public int getDato() 
 {
  return dato;
 }

 public void setDato(int dato) 
 {
  this.dato = dato;
 }

  public Nodo getSiguiente() 
  {
  return siguiente;
 }

 public void setSiguiente(Nodo siguiente) 
 {
  this.siguiente = siguiente;
 }
}

Clase Lista:


public class Lista 
{

 //Declaración de atributos
 private Nodo inicio;
 private Nodo fin;
 
 //Constructos de la clase Lista
 public Lista()
 {
  inicio=fin=null;
 }
 
 //Metodo para agregar un nodo al final
 public void agregarFin(int info)
 {
  
  Nodo nuevo = new Nodo(info, null);
 
  if(inicio==null)
  {
   inicio=fin=nuevo;
  }
  else
  {
   fin.setSiguiente(nuevo);
   fin = nuevo;
  }
 
 }
 
 //Metodo para imprimir los datos
 public void imprimir()
 {
  Nodo aux=inicio; 
  while(aux!=null)
  {
   System.out.println(aux.getDato());
   aux = aux.getSiguiente();
  } 
 }
 
 //Metodo apra eliminar los valores que superen un valor dado
 public void eliminar(int valor)
 {
  Nodo anterior=inicio;
  Nodo aux= inicio.getSiguiente();
  Nodo temp;
  while(aux!=null)
  {
   //Condicional simple para eliminacion de nodos
   if(aux.getDato() > valor)
   {
    temp=aux.getSiguiente();   
    anterior.setSiguiente(aux.getSiguiente()); 
    aux = temp;   
   }
   else
   {
    anterior=anterior.getSiguiente();
    aux=aux.getSiguiente();
   } 
  }
 }
}


Clase Principal:



import java.util.Scanner;

public class Principal 
{
 
 public static int leerEntero(String linea)
 {
  Scanner leer = new Scanner(System.in);
  System.out.println(linea);
  int dato = leer.nextInt();
  return dato; 
 }

 public static void main(String[] args) 
 {
  Lista coleccion = new Lista();
  int opcion;
  System.out.println("EJERCICIO 3 - LISTAS SIMPLES ENLAZADAS\n");
  do{
   System.out.println("MENU PRINCIPAL:");
   System.out.println("1.- Ingresar datos a la lista");
   System.out.println("2.- Imprimir Lista");
   System.out.println("3.- Eliminar datos que se pasan de un limite.");
   System.out.println("4.- Salir");
   opcion = leerEntero("Seleccione una opción:");
   
   switch(opcion)
   {
   case 1:
   {
    int nuevo = leerEntero("Ingrese el elemento que desee ingresar a la lista:");
    coleccion.agregarFin(nuevo);
    break;
   }
   case 2:
   {
    System.out.println("La lista ingresada es:");
    coleccion.imprimir();
    break;
   }
   case 3:
   {
    int valor = leerEntero("Ingrese el valor que sirva de limite:");
    coleccion.eliminar(valor);
    break;
   }
   case 4:
   {
    System.out.println("FIN DEL PROGRAMA");
    break;
   }
   }
  }while(opcion!=4);
 }
} 

Capturas de pantalla del programa:


Ejercicio 2 - Listas Simples Enlazadas

f
Enunciado:

Crear una lista simple enlazada de números enteros, se desea añadir un nodo entre dos nodos consecutivos; el dato del nuevo nodo debe ser la diferencia en valor absoluto de los dos nodos.

Ejemplo: si tengo la siguiente lista:

 |   20   |   |   43   |  |   17   |  |   4    |  |    11   |
Se debe insertar un dato entre 43 y 17
Reviso que exista secuencia
Luego calculo el valor absoluto de  (43-17)
Inserto entre esos elementos.
 |   20   |   |   43   |  |   26  |  |   17   |  |   4    |  |    11   |
Para realizar este ejercicio es necesario tener en cuenta, al igual que en el anterior, las definiciones sobre listas simples enlazadas,  así mismo de busquedas para encontrar el número que sirva como referencia para calcular el valor absoluto y el método correcto para insertar un nodo entre dos nodos. Se utiliza la libreria JOptionPane para establecer un mensaje emergente.

A continuación se muestra el código:
Clase Nodo:

public class Nodo 
{

 //Declaración de atributos
 private int dato;
 private Nodo siguiente;
 
 //Constructor Nodo null
 public Nodo(int dato)
 {
  this.dato=dato;
  this.siguiente=null;
 }
 //Constructor Nodo con parametro
 public Nodo(int dato, Nodo siguiente)
 {
  this.dato=dato;
  this.siguiente=siguiente;
 }

 //Metodos getters and setters
 public int getDato() {
  return dato;
 }

 public void setDato(int dato) {
  this.dato = dato;
 }

 public Nodo getSiguiente() {
  return siguiente;
 }

 public void setSiguiente(Nodo siguiente) {
  this.siguiente = siguiente;
 }
 
}

Clase Lista:

public class Lista 
{

 private Nodo inicio;
 private Nodo fin;
 
 public Lista()
 {
  inicio=fin=null;
 }
 
 //Metodo para agregar inicio
 public void agregarInicio(int info)
 {
  Nodo nuevo=new Nodo(info, inicio);
  if(inicio==null)
  {
   inicio=fin=nuevo;
  }
  inicio=nuevo;
 }
 
 //Metodo para agregar fin
 public void agregarFin(int info)
 {
  Nodo nuevo=new Nodo(info, null);
  if(inicio==null)
  {
   inicio=fin=nuevo;
  }
  else
  {
   fin.setSiguiente(nuevo);
   fin=nuevo;
  }
 }
 
 //Metodo para imprimir
 public void imprimir()
 {
  Nodo aux=inicio;
  while(aux!=null)
  {
   System.out.println(aux.getDato());
   aux=aux.getSiguiente();
  }
 }
 
 //Metodo para eliminar el nodo
 public void eliminarNodo(int numero)
 {
  if(inicio!=null)
  {
   if((inicio==fin)&&(inicio.getDato()==numero))
   {
    inicio=fin=null;
   }
   else if(inicio.getDato()==numero)
   {
    inicio=inicio.getSiguiente();
   }
   else
   {
    Nodo anterior=inicio;
    Nodo siguiente=inicio.getSiguiente();
    while((siguiente!=null)&&(siguiente.getDato()!=numero))
    {
     anterior=siguiente;
     siguiente=siguiente.getSiguiente();
    }
    if(siguiente!=null)
    {
     anterior.setSiguiente(siguiente.getSiguiente());
     if(siguiente==fin)
     {
      fin=anterior;
     }
    }
   }
  }
 }
 
 //Metodo para agregar un nodo
 public void agregarNodo(int numero)
 {
  if(inicio!=null)
  {
   if(inicio==fin && inicio.getDato()==numero)
   {
    inicio=fin=null;
   }
   else if(inicio.getDato()==numero)
   {
    inicio = inicio.getSiguiente();
   }
   else
   {    
    Nodo anterior = inicio;
    Nodo siguiente = inicio.getSiguiente();   
    while(siguiente!=null && anterior.getDato()!=numero)
    {
    anterior = siguiente;
    siguiente = siguiente.getSiguiente();
    }
    if (siguiente!=null)
    {
     Nodo nuevo = new Nodo(calculo(anterior.getDato(),siguiente.getDato()),siguiente);     
     anterior.setSiguiente(nuevo);
     nuevo.setSiguiente(siguiente);
     if(siguiente == fin)
     {
      fin = anterior;
     }
    }
   }  
  }
 }

 //Metodo para calcular el valor absoluto entre dos numeros ubicados en los nodos
 public int calculo(int primer, int segundo)
 {
  int num = primer -segundo;   
  num =Math.abs(num);
  return num;  
 }

}

Clase Principal:
import javax.swing.JOptionPane;

public class Principal {

 public static void main(String[] args) 
 {
 Lista array = new Lista();
  
  array.agregarInicio(17);
  array.agregarInicio(43);
  array.agregarInicio(20);
  array.agregarFin(4);
  array.agregarFin(11);
  System.out.println("Lista inicial");
  array.imprimir();
  
  int agregar = Integer.parseInt(JOptionPane.showInputDialog("Ingrese el numero para que el nuevo valor se ubique despues de este"));
  
  array.agregarNodo(agregar);
  System.out.println("Nueva lista:");
  array.imprimir(); 
 }
}
Capturas de pantalla del programa:




Ejercicio 1 - Listas Simples

Enunciado:


Crear una lista simple la cual debe ingresar números reales, luego ordenarlos de mayor a menor, imprimir la lista, obtener el promedio de los valores de cada lista, comprobar cuál es el valor que más se repite en la lista.

Para realizar este ejercicio es necesario recordar la definición de listas simples, las cuales tienen como principal característica que solo se puede avanzar, no se puede retroceder. Dicho esto se procedió a realizar un ordenamiento burbuja para que los elementos se comparen y se ordenen de mayor a menor. Para realizar un ordenamiento burbuja se debe utilizar sentencias for anidadas.

A continuación se muestra el código:

Clase Nodo:

public class Nodo 
{

 //Declaración de atributos
 private int dato;
 private Nodo siguiente;
 
 //Constructor Nodo null
 public Nodo(int dato)
 {
  this.dato=dato;
  this.siguiente=null;
 }
 //Constructor Nodo con parametro
 public Nodo(int dato, Nodo siguiente)
 {
  this.dato=dato;
  this.siguiente=siguiente;
 }

 //Metodos getters and setters
 public int getDato() {
  return dato;
 }

 public void setDato(int dato) {
  this.dato = dato;
 }

 public Nodo getSiguiente() {
  return siguiente;
 }

 public void setSiguiente(Nodo siguiente) {
  this.siguiente = siguiente;
 }
 
}

Clase Lista:




public class Lista 
{

 private Nodo inicio;
 private Nodo fin;
 
 public Lista()
 {
  inicio=fin=null;
 }
 
 //Metodo para agregar inicio
 public void agregarInicio(int info)
 {
  Nodo nuevo=new Nodo(info, inicio);
  if(inicio==null)
  {
   inicio=fin=nuevo;
  }
  inicio=nuevo;
 }
 
 //Metodo para agregar fin
 public void agregarFin(int info)
 {
  Nodo nuevo=new Nodo(info, null);
  if(inicio==null)
  {
   inicio=fin=nuevo;
  }
  else
  {
   fin.setSiguiente(nuevo);
   fin=nuevo;
  }
 }
 
 //Metodo para imprimir
 public void imprimir()
 {
  Nodo aux=inicio;
  while(aux!=null)
  {
   System.out.println(aux.getDato());
   aux=aux.getSiguiente();
  }
 }
 
 //Metodo para eliminar el nodo
 public void eliminarNodo(int numero)
 {
  if(inicio!=null)
  {
   if((inicio==fin)&&(inicio.getDato()==numero))
   {
    inicio=fin=null;
   }
   else if(inicio.getDato()==numero)
   {
    inicio=inicio.getSiguiente();
   }
   else
   {
    Nodo anterior=inicio;
    Nodo siguiente=inicio.getSiguiente();
    while((siguiente!=null)&&(siguiente.getDato()!=numero))
    {
     anterior=siguiente;
     siguiente=siguiente.getSiguiente();
    }
    if(siguiente!=null)
    {
     anterior.setSiguiente(siguiente.getSiguiente());
     if(siguiente==fin)
     {
      fin=anterior;
     }
    }
   }
  }
 }
 
 //Metodo ordenar de mayor a menor
 public void ordenarMayorMenor(int info)
 {
  int aux;
  Nodo recorrer=inicio;
  int array[]=new int [info];
  for(int i=0;i<info;i++)               
{
   array[i]=recorrer.getDato();
   recorrer=recorrer.getSiguiente();
  }
  for(int k=0;k<info;k++)
  {
   for(int j=k+1;j<info;j++)
   {
    if(array[k]<array[j])
    {
     aux=array[k];
     array[k]=array[j];
     array[j]=aux;
    }
   }
  }
  Lista nueva=new Lista();
  for(int f=0;f<info;f++)
  {
   nueva.agregarFin(array[f]);
  }
  nueva.imprimir();
 }
 
 //Metodo para calcular el promedio de la lista
 public void promedio()
 {
  Nodo aux=inicio;
  int suma=0;
  double promedio;
  while(aux!=null)
  {
   suma= suma+ aux.getDato();
   aux=aux.getSiguiente();
  }
  promedio=suma/5;
  System.out.println("El promedio de la lista es:"+promedio);
 }
 
//Metodo para obtener el numero que más se repite y su frecuencia de repeticion
 public void repeticiones(int inf)
 {
  int frecTemp, frecModa=0, moda=-1;
  Nodo recorrer=inicio;
  int array[]=new int [inf];
  for(int i=0;i<inf;i++)
  {
  array[i]=recorrer.getDato();
  recorrer=recorrer.getSiguiente();
  }
  for(int i=0;i<array.length-1;i++)
  {
   frecTemp=1;
   for(int j=i+1;j<array.length;j++)
   {
    if(array[i]==array[j])
     frecTemp++;
   }
   if(frecTemp>frecModa)
   {
    frecModa=frecTemp;
    moda=array[i];
   }
  }
  System.out.println("El elemento más repetido en la lista es: "+moda+", con una frecuencia de: "+frecModa);
 }
}

Clase Principal:




import java.util.Scanner;

public class Principal 
{

 public static void main(String[] args) 
 {
 Scanner lectura=new Scanner(System.in);
 Lista coleccion=new Lista();
 int n=5, dato;
 System.out.println("Ejercicio 1- Listas Simples\n");
 for(int i=0;i<n;i++)
 {
  System.out.println("Ingrese el elemento "+(i+1)+" de la lista");
  dato=lectura.nextInt();
  coleccion.agregarInicio(dato);
 }
 System.out.println("Lista ingresada:");
 coleccion.imprimir();
 
 System.out.println("\nLista ordenada de mayor a menor");
 coleccion.ordenarMayorMenor(n);
 
 coleccion.promedio();
        coleccion.repeticiones(n);
 }
}

Capturas de Pantalla: