Implementación
de Colas con
Listas Enlazadas
Taller de
Algoritmos y
Estructuras
de Datos I
1
Implementación de Colas
con listas enlazadas
En la estructura de datos de tipo cola también tenemos 2 formas de
implementarla, al igual que en las pilas, podemos utilizar un vector
que almacena los elementos de forma contigua y la segunda consiste
en almacenar los elementos de forma no contigua por medio de una
lista enlazada.
Las operaciones que debemos implementar en una estructura de datos de tipo
Cola son las siguientes:
Creación: crea una cola vacía
Inserción: agrega un nuevo elemento en la cola
insertar(x)
Borrado: elimina el elemento mas antiguo, si la cola no esta vacía
x = quitarPrimero()
Consulta: Cola Vacía
Interfaz Cola
La interfaz cola tiene los siguientes métodos que deberán ser
implementados tanto en la cola vector como en la cola lista enlazada
public interface Cola{
public boolean esVacia();
public void vaciar();
public void insertar(Object o);
public Object primero()
throws DesbordamientoInferior;
public Object quitarPrimero()
throws DesbordamientoInferior;
}
Colas Implementadas con Vector
La forma más sencilla de implementar una cola consiste en almacenar
sus elementos en un vector, colocando el elemento en cabeza en la
primera posición del mismo (es decir, en el índice 0). Si fin
representa la posición del último elemento de la cola, entonces
para insertar un elemento no tenemos más que incrementar fin,
insertando el elemento en esa posición. El problema es que la operación
quitarPrimero es muy costosa, esto es porque debido a la exigencia de
posición los elementos de la cola desde el principio del vector, con lo cual
forzamos a la rutina quitarPrimero a desplazar la posición de todo los
elementos del vector, una vez eliminado el primero. Para resolver el
problema, basta con incrementar cabeza cuando se realiza una operación
quitarPrimero, en lugar de desplazar todos los elementos. Entonces cuando
la cola tiene un único elemento, fin y cabeza representa la posición en el
vector de dicho elemento. Siguiendo esta línea en una lista vacía fin y
cabeza se representan con -1.
Para vectores de longitud fija como los arrays en Java, esto podría causar
que no quede mas espacio libre en la cola. Sin embargo podría existir
espacio libre a reutilizar. Todas las posiciones anteriores a cabeza están
vacías, por lo tanto se podrían reciclar. Con tal objetivo se introduce la
circularidad: cuando fin y cabeza rebasan la posición del vector, se
reposicionan en el principio del mismo. Este nombre recibe el nombre de
implementación circular.
public class ColaVector implements Cola{
private static final int N=1000;
private int capacidad;
private Object[] S;
private int cabeza = 0;
private int fin = -1;
private int tamanyoActual = 0;
public ColaVector(){ this(N); }
public ColaVector( int cap ){
capacidad = cap;
S = new Object[capacidad];
// Método que inserta un nuevo elemento
public void insertar( Object o )
throws DesbordamientoInferior
if (tamanyo() == capacidad)
throw new DesbordamientoInferior(“Cola llena”);
fin = incrementar( fin );
S[fin] = o;
tamanyoActual++;
// Método que quita el primer elemento y devuelve la cabeza
public Object quitarPrimero()throws DesbordamientoInferior{
if( esVacia() )
throw new DesbordamientoInferior(“Cola vacía”);
tamanyoActual--;
Object el = S[ cabeza ];
cabeza = incrementar( cabeza );
return el;
public Object primero() throws DesbordamientoInferior{
if( esVacia() )
throw new DesbordamientoInferior(“Cola vacía”);
tamanyoActual--;
return S[ cabeza ];
Colas implementadas con listas enlazadas
Las colas pueden implementarse empleando lista enlazada, siempre que
se mantengan referencia que apunten al principio y fin de la lista. Los
métodos de las colas son prácticamente idénticos a los de las pilas.
Nodo Cola
public class Nodo {
private Object dato;
private Nodo sig;
private Nodo ant;
public Object getDato() {
return dato;
public void setDato(Object dato) {
this.dato = dato;
public Nodo getSig() {
return sig;
public void setSig(Nodo sig) {
this.sig = sig;
public Nodo getAnt() {
return ant;
public void setAnt(Nodo ant) {
this.ant = ant;
public Nodo(Object dato) {
this.dato = dato;
this.sig = null;
this.ant = null;
public Nodo(Object dato, Nodo sig, Nodo ant) {
this.dato = dato;
this.sig = sig;
this.ant = ant;
public Nodo(Object dato, Nodo sig) {
this.dato = dato;
this.sig = sig;
// Implementación con nodos cabecera y fin
public class Cola implements Cola{
private Nodo cab;
private Nodo fin;
private Nodo sig;
public Nodo getCab() {
return cab;
public void setCab(Nodo cab) {
this.cab = cab;
public Nodo getFin() {
return fin;
public void setFin(Nodo fin) {
this.fin = fin;
public Nodo getSig() {
return sig;
public void setSig(Nodo sig) {
this.sig = sig;
// Inserta un Nuevo objeto
public void insertar(Object dato){
Nodo nvo;
if (esVacio ()){
nvo = new Nodo(dato, sig);
this.cab = nvo;
nvo.setSig(null);
this.fin = nvo;
nvo.setDato(dato);}
else{
//nvo = new Nodo ();
nvo = new Nodo(dato, sig);
this.fin.setSig(nvo);
nvo.setDato(dato);
this.fin.setSig(nvo);
nvo.setSig(null);
// Método que quita el primer elemento y devuelve la nueva cabecera
public Object quitarPrimero(){
if (esVacio())
System.out.println ("La cola está vacía.");
Object valorDevuelto = this.cab.getDato();
this.cab = cab.getSig();
return valorDevuelto;
public void buscar() {
Nodo aux = null;
aux.setSig(this.cab.getSig());
System.out.println (aux.getDato());
aux = aux.getSig();
public boolean esVacio() {
return this.cab == null;
public void listar() {
Nodo aux = null;
aux = this.cab;
do{
System.out.println (aux.getDato());
aux = aux.getSig();
}while (aux != null);
public Object primero() {
if (esVacio())
System.out.println ("La cola está vacía.");
return (cab.getDato());
public void vaciar() {
this.cab = this.fin = null;
Caso Práctico
Ahora realizaremos el ejemplo de la institución educativa pero almacenando
los alumnos en una estructura de datos de tipo Cola. La implementación la
realizaremos a través de una lista enlazada simple. Las clases intervinientes
son las mismas que el ejemplo anterior: Personas, Alumnos y Materia.
Alumno extiende de Persona, y Alumno puede cursar una o varias Materias.
Desde una clase Principal que contienen el método main utilizaremos una
estructura de tipo Cola implementada con lista enlazada para almacenar los
alumnos. Se utilizara una interfaz de ingreso de datos con la clase
ConsoleWindow para el ingreso de datos con teclado. También se utiliza una
clase de validación.
Las clases Persona, Alumno y Materia conservan los mismos atributos
y métodos del caso práctico anterior.
Clase Persona
public class Persona {
private int dni;
private String nomb;
private String apel;
public Persona (int dni,String nomb,String apel){
this.dni = dni;
this.nomb = nomb;
this.apel = apel;
public int getDni() {
return dni;
public void setDni(int dni) {
this.dni = dni;
public String getNomb() {
return nomb;
public void setNomb(String nomb) {
this.nomb = nomb;
public String getApel() {
return apel;
public void setApel(String apel) {
this.apel = apel;
public String toString(){
String aux;
aux="D.N.I: " + dni + "\nNombre: " + nomb + "\nApellido: " +
apel;
return aux;
}
Clase Alumno
public class Alumno extends Persona{
private String legajo;
private Materia Mat[] = new Materia[5];
public Alumno(int dni, String nomb, String apel, String legajo) {
super(dni, nomb, apel);
this.legajo = legajo;
for (int i = 0; i < Mat.length; i++) {
Mat[i] = null;
public String getLegajo() {
return legajo;
public void setLegajo(String legajo) {
this.legajo = legajo;
public Materia[] getMat() {
return Mat;
public void setMat(Materia[] mat) {
Mat = mat;
}
public boolean cargarAlumno(Materia m) {
for (int i = 0; i < Mat.length; i++) {
if (Mat[i] == null) {
Mat[i] = m;
return true;
return false;
public String toString() {
String aux;
aux = super.toString();
aux += "\nLegajo: " + legajo;
aux += "\nMaterias: ";
for (int i = 0; i < Mat.length; i++) {
aux += "\n" + Mat[i];
return aux;
Clase Materia
public class Materia {
private String denom;
private int semestre;
public Materia (String demon,int semestre){
this.denom = demon;
this.semestre = semestre;
public String getDenom() {
return denom;
public void setDenom(String denom) {
this.denom = denom;
public int getSemestre() {
return semestre;
public void setSemestre(int semestre) {
this.semestre = semestre;
public String toString(){
String aux;
aux="Denominacion: " + denom + " - Semestre: " +
semestre;
return aux;
La clase nodo tiene 2 atributos: El dato que contiene el objeto a
guardar y el nodo siguiente.
Clase Nodo
public class Nodo {
private Object dato;
private Nodo sig;
public Nodo() {
this.dato = null;
this.sig = null;
public Object getDato() {
return dato;
public void setDato(Object dato) {
this.dato = dato;
public Nodo getSig() {
return sig;
public void setSig(Nodo sig) {
this.sig = sig;
public Nodo(Object dato) {
this.dato = dato;
public Nodo(Object dato, Nodo sig) {
this.dato = dato;
this.sig = sig;
Clase Cola Lista Enlazada
Utiliza 2 nodos auxiliares para determinar el primer y ultimo nodo.
Recordamos que la inserción y eliminación se realizan por los extremos
opuestos de la cola
public class ColaLi implements Cola {
public Nodo pri;
public Nodo ult;
public ColaLi() {
pri = new Nodo();
pri.setSig(null);
ult = new Nodo();
ult.setSig(null);
public ColaLi(Nodo pri, Nodo ult) {
this.pri = null;
this.ult = null;
// Inserta un Nuevo objeto
public void insertar(Object x) {
Nodo nuevo = new Nodo(x);
if (pri.getSig() == null) {
pri.setSig(nuevo );
} else {
(ult.getSig()).setSig(nuevo ); //del primer nodo asigna la
referencia al nodo nuevo
ult.setSig(nuevo );
// Pregunta si la cola es vacía
public boolean esVacia() {
boolean aux = false;
if (pri.getSig() == null) {
aux = true;
return aux;
}
public void vaciar() {
pri.setSig(null);
ult.setSig(null);
// Devuelve el primer elemento (el más antiguo)
public Object primero() throws DesbordamientoInferior {
if (esVacia())
System.out.println ("La cola está vacía.");
return (pri.getSig().getDato());
public Object quitarPrimero() throws DesbordamientoInferior {
if (esVacia())
System.out.println ("La cola está vacía.");
else {
pri.setSig((pri.getSig()).getSig());
if (pri.getSig() == null) {
ult.setSig(null);
return pri.getSig().getDato();
}
Clase Leer
Se utiliza para el ingreso de datos por consola.
import element.*;
public class Leer {
public static String leerString(ConsoleWindow c)
String s =" ";
try
{s = c.input.readLine();}
catch(Exception e)
c.out.println("error ingreso otra cosa que no es
String");
c.out.println(e.getMessage());
leerString(c);
return s;
Clase Salida
Se utiliza para mostrar los elementos de salida por al consola
import element.*;
public class Salida {
public static void cerrar()
{
ConsoleWindow c = new ConsoleWindow();
c.out.println("Apriete cualquier tecla para continuar y luego
ENTER");
c.input.readInt();
System.exit(0);
public static void cerrar(ConsoleWindow c)
c.out.println("Apriete cualquier tecla para continuar y luego
ENTER");
c.input.readInt();
System.exit(0);
Clase Validar
Se utiliza para validar los datos de entrada. En Este caso se muestran 2
metodos validar enteros y validar long.
import element.ConsoleWindow;
public class Validar
public static int validarInt(String op, ConsoleWindow c)
int temp = 0;
try{
temp =Integer.parseInt(op);}
catch(Exception e){
return -1;
return temp;
public static double validarDouble(String op, ConsoleWindow c)
double temp = 0;
try{
temp = Double.parseDouble(op);}
catch(Exception e){
return -1;
return temp;
Clase Principal
Contiene el menú principal y el ingreso de datos según la opción
respectiva.
import control.*;
import consola.*;
import element.*;
import modelo.Alumno;
import modelo.ColaLi;
import modelo.DesbordamientoInferior;
import modelo.Materia;
public class Principal
private static double paramD = 0;
private static String op = " ";
private static int op1 = 0;
private static String paramS = " ";
private static String auxS = " ";
private static String nomb, apel, legajo="";
private static int paramI = 0;
private static final int cantAlumnos=3;
private static int dni = 0;
private static Materia [] materias = new Materia [3];
/*
* Para simplificar el problema
* Se ingresa un array de 3 Materias las cuales son asignadas a los
alumnos
* Para simplificar se ingresa una estructura de tipo Cola para 2
alumnos
* */
public static void main(String[] args) throws
DesbordamientoInferior {
ConsoleWindow c = new ConsoleWindow();
c.out.println("Bienvenido al sistema Sos un animal?");
do
{
c.out.println("Selecciona una opcion acorde a su
necesidad");
c.out.println("**********************************************
******");
c.out.println("1- Ingresar Materias");
c.out.println("2- Ingresar Alumnos Cola");
c.out.println("0- SALIR");
c.out.println("**********************************************
******");
op = Leer.leerString(c);
op1 = Validar.validarInt(op,c);
switch (op1)
case 1:
for(int i=0;i<materias.length;i++)
c.out.println("Ingrese la
denominacion de la materia");
paramS =
Leer.leerString(c);
c.out.println("Ingrese el semestre de la
materia");
auxS = Leer.leerString(c);
paramI =
Validar.validarInt(auxS, c);
materias[i] = new Materia(paramS,paramI);
}
break;
case 2:
Alumno alu=null;
ColaLi cl = new ColaLi();
for(int i=0;i<cantAlumnos;i++)
// Ingreso los Datos
c.out.println("Ingrese el legajo
del alumno: ");
legajo = Leer.leerString(c);
c.out.println("Ingreseel el
apellido del alumno: ");
apel = Leer.leerString(c);
c.out.println("Ingreseel el nombre
del alumno: ");
nomb = Leer.leerString(c);
c.out.println("Ingrese el dni: ");
auxS = Leer.leerString(c);
dni = Validar.validarInt(auxS,
c);
alu = new
Alumno(dni,nomb,apel,legajo);
alu.setMat(materias);
c.out.println("--------Insertar-
--------");
cl.insertar(alu);
c.out.println("--------Muestro
Primero---------");
c.out.println(cl.primero().toString());
// Desapilo y muestro
c.out.println("\n---------Quitar Primero--------");
cl.quitarPrimero();
c.out.println("---Nueva Cima----");
c.out.println(cl.primero().toString());
break;
case 0:
Salida.cerrar(c);
break;
default:
c.out.println("error en el ingreso,
reingrese");
break;
}while(op1!=0);
}
Referencia Bibliográfica
Mark Allen Weiss, “Estructuras de Datos en Java”, ed. Addison Wesley. (2000)
Bibliografía Ampliatoria
En el caso que quieras ampliar los conceptos que hemos visto te
recomiendo la siguiente bibliografía
Fundamentos de algoritmo y programación , autor Lage Fernando
Introducción a la programación, autor Ramirez Felipe
Algoritmo y Programación, autor Perez Berro
Introducción al diseño y análisis de algoritmos, autor Leer R.C.T.
Metodología de la Programación, autor Cairo B.
C. Algoritmos, programación y estructuras de datos, autor Joyanes
Aguilar
Matemática Discreta y Algoritmos, autor Perez Julio
Algoritmo y estructura de datos una perspectiva en C, autor
Joyanes Aguilar
Algoritmos datos y programas, autor De Giusti
Algoritmos fundamentales, autor Knuth Donald
Estructuras de datos y algoritmos, autor Hernandez Roberto
Introducción al análisis de algoritmos, autor Sanchez Velásquez
Diseño y análisis de algoritmos, autor Torres Carmen