Está en la página 1de 21

Área: Tecnología

Estructura de datos

M2 Introducción a colas
Módulo: 2
Curso: Estructura de datos

Mapa de Contenido

Clases

Conceptos básicos de Java Atributos

Métodos

Teoría de colas
Introducción a colas
Diseño de una estructura de
datos tipos cola

Cola circular

Operación con colas

Gestión de datos

Aplicación de una cola en un


problema práctico
Módulo: 2
Curso: Estructura de datos

Índice

Introducción ............................................................................................................................................................................................................ 4
1. Conceptos básicos de Java........................................................................................................................................................................... 5
1.1 Clases ................................................................................................................................................................................. 5
1.2 Atributos ............................................................................................................................................................................ 6
1.3 Métodos ............................................................................................................................................................................ 7
2. Diseño de una estructura de datos tipos cola .................................................................................................................................... 12
2.1 Teoría de colas ................................................................................................................................................................. 12
2.2 Cola circular ..................................................................................................................................................................... 16
3. Gestión de datos ............................................................................................................................................................................................ 19
3.1 Operación con Colas ........................................................................................................................................................ 19
3.2 Aplicación de una cola en un problema práctico ............................................................................................................ 20
Cierre ....................................................................................................................................................................................................................... 21
Referencias bibliográficas ................................................................................................................................................................................ 21
Módulo: 2
Curso: Estructura de datos

Resultado de aprendizaje

Analiza conceptos avanzados de Java, diseñando una cola mediante el algoritmo correspondiente,
en un contexto de gestión de datos.

Introducción
En el primer módulo revisamos Listas. Para poder incorporar los conceptos de listas, primero realizamos
una introducción a algunos conceptos básicos de java. Variables, operadores y estructuras de control en
lenguaje java, que nos permitió analizar y desarrollar las diferentes estructuras requeridas para una lista
y entender el funcionamiento y la lógica de estas.

Siguiendo en la misma línea, ahora profundizaremos en otros conceptos de java tales como clases,
atributos y métodos. Con ellos vamos a comprender mejor como aplicarlos en la creación de las diferentes
estructuras de datos. Abordaremos, entonces, los conceptos y métodos prácticos que tienen relación con
el TDA Cola.

Una cola es una estructura que es concebida como tal para solucionar múltiples problemas que tienen
relación con la acumulación y gestión elementos que deben ser atendidos de acuerdo con una prioridad.

Podemos definir a una cola como “aquella estructura de datos que se encarga de almacenar elementos,
y opera de acuerdo con la regla FIFO (First In, First Out o el primero que entra, es el primero que sale)”.
Dicha prioridad viene expresada por orden de llegada. Lo mismo que ocurre en “una cola o fila de
supermercado”

A medida que avanza el recorrido de la cola, si se siguen agregando elementos al final y siguen saliendo
por el principio, puede llegar el momento en que coincida el punto de entrada y salida. Es en este caso
que se utilizan las colas circulares.

Para llevarlo a una solución práctica aplicada en computación, podríamos pensar en la resolución de
múltiples trabajos de impresión, o también en la utilización compartida de una memoria aplicada a
diferentes recursos.

Aprenderemos que la estructura responde a una lógica posicional y que, por su arquitectura, se
conforman algunos componentes (todos ellos abstractos) que manifiestan coherencia para las distintas
operaciones.

Pág. 4
Módulo: 2
Curso: Estructura de datos

1. Conceptos básicos de Java


Comenzamos revisando algunos conceptos de Java que nos van a ayudar a comprender mejor las
implementaciones de las TDA.

1.1 Clases
Una clase es la descripción de un objeto. Pero mejor veámoslo con un ejemplo:

Ejemplo

En Eclipse para crear una clase se hace desde el menú del Package Explorer. Por convención, las
clases siempre se nombran con su primera letra en mayúscula.

Fuente: elaboración propia.

Para esta clase Estudiante, podemos crear diferentes objetos tantos como necesitemos:

Pág. 5
Módulo: 2
Curso: Estructura de datos

nombre nombre constructor


clase objeto

Estudiante estudiante 1 = new Estudiante ();


Estudiante estudiante 2 = new Estudiante ();

La palabra “new” es una palabra reservada para crear objetos. Los constructores son métodos que
veremos más adelante.

También podemos definir clases internas, que se utilizan en el caso de que sean muy pequeñas. Se
colocan dentro de otra clase, que pasa a ser su clase contenedora.

1.2 Atributos
Una vez creada nuestra clase, agregaremos atributos a esta clase. Los atributos contendrán la
información de todos los objetos que se instancien en la clase.

Declaremos, entonces, atributos para nuestra clase Estudiante:

Fuente: elaboración propia.

Pág. 6
Módulo: 2
Curso: Estructura de datos

1.3 Métodos
Los métodos son las acciones que van a realizar los objetos de la clase, una vez que se hayan creado
o instanciado por supuesto.

El primer método que vamos a crear es el main:

Modificador valor de
de acceso retorno

Public static void main (String [] args)

El valor de retorno void no retorna nada. Si retornamos un número entonces lo reemplazamos por int.

Dentro de este método vamos a instanciar nuestros objetos:

Fuente: elaboración propia.

Pág. 7
Módulo: 2
Curso: Estructura de datos

Como vemos, al ya tener creados nuestros objetos, el asistente nos muestra todos los atributos
disponibles que puede tener.

Veamos dos objetos instanciados con atributos:

Fuente: elaboración propia.

Y en lugar de tener las variables ya almacenadas, vamos a solicitar al usuario que ingrese los números.
Vamos a realizar esto mediante un método:

Tenemos la clase Estudiante, donde creamos sus atributos y el método leerDato:

Pág. 8
Módulo: 2
Curso: Estructura de datos

Fuente: elaboración propia.

La clase Main, donde vamos a crear el método main, llamaremos a la clase Estudiante.

Es siempre más ordenado tener por separado las clases, con los diferentes métodos según lo que
vayamos requiriendo.

Pág. 9
Módulo: 2
Curso: Estructura de datos

Fuente: elaboración propia.

Una vez que ejecutamos, entonces el programa solicitará al usuario el ingreso de datos por pantalla:

Pág. 10
Módulo: 2
Curso: Estructura de datos

Fuente: elaboración propia.

Ahora, practica con el siguiente ejercicio:

Procedimiento

Vas a mejorar el programa que venimos revisando en el ejemplo:

1. Crea 10 estudiantes. Para cada estudiante vas a solicitar que el usuario ingrese su nombre,
apellido, y cuatro notas bimestrales.
2. Luego, creando los métodos necesarios, vas a mostrar los promedios para cada estudiante.

Una vez que tengas listo el ejercicio, puedes mostrarlo a tu docente.

Pág. 11
Módulo: 2
Curso: Estructura de datos

2. Diseño de una estructura de datos tipos cola


2.1 Teoría de colas
Una cola es una estructura que opera con la lógica de almacenar elementos ingresándolos por un
extremo y eliminándolos por el otro. Dicha lógica se denomina FIFO, vale decir “el primero que entra
es el primero que sale”.

Esta estructura, con su lógica y característica muy simple, permite solucionar múltiples problemas que
tienen relación con el orden de llegada, arribo o presentación, para luego la gestión de salida con el
mismo orden de almacenamiento.

Las colas son muy utilizadas en la computación y la informática, puesto que, por su diseño y simplicidad,
la estructura es aplicable para la solución de un conjunto de problemas cotidianos y recurrentes. Los
sistemas operativos fueron unos de los primeros en crear y utilizar las colas para problemas como la
multiprogramación, la calendarización, manejo de procesos, etc.

Como TDA, las colas tienen diferentes formas de implementación y varias operaciones que por su
naturaleza se utilizarían en todas ellas.

Las operaciones más básicas y necesarias son:

Creación Inserción Eliminación

Además de lo anterior, el TDA Cola cuenta con funciones útiles que permiten la gestión de esta respecto
del contexto. Tales funciones son:

Número de
Cola vacía Cola llena Frente
elementos

Si imaginamos la generación de una cola estática, veríamos algo como lo siguiente:

Pág. 12
Módulo: 2
Curso: Estructura de datos

Ejemplo

Se genera el arreglo, con la cantidad de elementos requeridos, en este caso 10.

Fuente: elaboración propia.

Luego, se genera los apuntadores que se inicializan en la posición inicial:

Fuente: elaboración propia.

Luego, al momento de insertar elementos, el apuntador de Fin va siendo desplazado hacia la


derecha (en la práctica se va incrementando en un sentido), marcando la posición de que utilizará
el siguiente elemento al hacer la inserción. En la siguiente imagen se ejemplifica la inserción de un
nuevo elemento en la posición 4 lo cual desplaza al apuntador fin a la posición 5. No olvidar que los
elementos de un arreglo parten desde la posición 0 hasta N.

Fuente: elaboración propia.

Pág. 13
Módulo: 2
Curso: Estructura de datos

Cuando la cola comienza a liberar elementos, entonces se entrega el elemento de la posición


apuntada por Frente, la cual se trasladará “persiguiendo” al apuntador o marcador Fin. Como se
aprecia en la siguiente imagen:

Fuente: elaboración propia.

Como se puede apreciar, conforme la cola se va llenado, avanza el apuntador Fin, puesto que es el
último que entra.

Por otra parte, conforme la cola se va liberando, se devuelve el valor de la posición apuntada por el
marcador o puntero “Frente”, y éste avanza a la posición siguiente, el cual será el nuevo Frente.

Analicemos la implementación de la cola con estructuras estáticas, ahora utilizando el lenguaje de


programación, vamos a implementar una cola con 10 elementos de tipo entero:

class ColaLineal {
private static final int MAXTAMQ = 10;
protected int frente;
protected int fin;
protected int [] listaCola;
public ColaLineal() {
frente = 0;
fin = -1;
listaCola = new int [MAXTAMQ];
}
}

Como se puede observar, hemos declarado una clase ColaLineal la cual cuenta con su una variable
estática Final (MAXTAMQ), que utilizaremos para definir la cantidad de elementos del arreglo, dos
variables que actuarán como marcadores posicionales de los elementos inicial (frente), final (fin), y el
arreglo de enteros (listaCola).

Pág. 14
Módulo: 2
Curso: Estructura de datos

El constructor de la clase inicializa las variables marcadores e instancia el arreglo con la cantidad de
elementos definidos en la constante MAXTAMQ.

Hasta ahora se puede apreciar que los apuntadores difieren entre sí, lo cual implica que si la variable fin
es menor que la variable frente entonces define a la cola como vacía.

Dado lo anterior, es posible escribir colaVacia, que será la primera función de la clase, la cual tiene la
responsabilidad de informarnos de aquello:

La función colaVacia, será una función Booleana:

public boolean colaVacia() {


return frente > fin;
}

La función luce muy sencilla y elegante, puesto que retorna el cálculo booleano implícitamente. Una
forma más evidente o explícita para escribir la función sería la siguiente versión.

public boolean colaVacia_V2() {


if (frente > fin)
return true;
else
return false;
}

Para saber si la cola está llena en esta implementación lineal del arreglo entonces basta con informarse
del valor del marcador fin, el cual si es igual a la constante MAXTAMQ -1, entonces damos por hecho
que la cola se encuentra llena:

public boolean colaLlena() {


return fin == MAXTAMQ-1;
}

Surge una pregunta: ¿por qué fin se compara con MAXTAMQ – 1? Para responder esta pregunta, basta
con observar dos condiciones planteadas en el algoritmo:

1. La condición de que la variable fin es la posición del último elemento ingresado y el primero tiene
valor 0.
2. El arreglo de n elementos tiene como valor posicional máximo a n-1, dado que el primer elemento
es 0.

Pág. 15
Módulo: 2
Curso: Estructura de datos

2.2 Cola circular


Como solución de lo anterior, se propone la gestión de los
marcadores tal que se trate al arreglo como una estructura circular.

Gráficamente, la estructura podría verse tal como se muestra en la


imagen superior derecha.

La lógica que opera sobre la cola “circular” es que, utilizando el


cálculo del módulo, los valores de los apuntadores van aumentando
y automáticamente volviendo a 0.

La pregunta que cabe es: ¿cómo es eso del cálculo del módulo?

El resto o módulo es el valor residual de una división exacta o


inexacta.
Estructura circular.
Fuente: elaboración propia.

Procedimiento

Como ya sabemos, la división se compone de:

Dividendo: Divisor = cuociente


Resto

Por ejemplo, el módulo de 10: 3 es 1, porque:

10: 3 = 3
1

Generalizando, para obtener el resto o módulo se realiza el cálculo:

Resto = Dividendo – (Divisor x Cociente)

Utilizando el ejemplo anterior, el resto o módulo de 10 / 3,

10 – (3 * 3) = 1

Finalmente, incorporando una función con la responsabilidad de los cálculos posicionales:

Pág. 16
Módulo: 2
Curso: Estructura de datos

private int siguiente(int r) {


return (r+1) % MAXTAMQ;
}

Entonces, se puede invocar a dicha función en los procedimientos respectivos, para tratar o transformar
a la cola, teniendo presente que se implementa utilizando un arreglo, en una cola circular:

El procedimiento de inserción, el cual ahora invoca a la función siguiente para obtener el valor posicional
de su apuntador o marcador fin.

public void insertar(int elemento) throws Exception {


if (!colaLlena()){
fin = siguiente(fin);
listaCola[fin] = elemento;
} else throw new Exception("Overflow en la cola");
}

Luego, la modificación del procedimiento quitar, incorpora de la misma forma, ahora al marcador frente:

public int quitar() throws Exception {


if (!colaVacia()) {
int tm = listaCola[frente];
frente = siguiente(frente);
return tm;
} else throw new Exception("Cola vacía ");
}

Luego, las funciones que informan el estado de la cola actúan en consecuencia:

public boolean colaVacia() {


return frente == siguiente(fin);
}

public boolean colaLlena() {


return frente == siguiente(siguiente(fin));
}

Reflexionando respecto de ambas implementaciones, se observa que la implementación de la cola


circular es bastante más eficiente dado que evita restar tiempo y recursos a la máquina para el
reordenamiento de los elementos y procura la utilización completa del array, aunque debido a la lógica
de los apuntadores, se pierde un espacio del arreglo.

Pág. 17
Módulo: 2
Curso: Estructura de datos

Sin embargo, persisten los problemas de reserva de espacio estático, además del gran riesgo de que la
reserva del espacio sea insuficiente y que, por falta de espacio reservado, se deberá redimensionar al
arreglo, interrumpiendo la ejecución del programa y volviendo a iniciarla.

Para evitar lo anterior, es que aparecen las estructuras dinámicas como las listas enlazadas y listas
doblemente enlazadas. Gracias a ellas, se puede escribir implementaciones mucho más eficientes y sin
las restricciones mencionadas en el párrafo anterior.

Pág. 18
Módulo: 2
Curso: Estructura de datos

3. Gestión de datos
3.1 Operación con Colas
Agregar un elemento es muy simple, dado que solo debe asignarse la posición fin +1 (en su defecto,
incrementar la variable, luego asignar su valor posicional respecto de arreglo), siempre invocando a la
función colaLlena, la cual nos informará si es posible agregar más datos a la cola:

public void insertar( int elemento) throws Exception {


if (!colaLlena()) {
listaCola[++fin] = elemento;
} else throw new Exception("Overflow en la cola");
}

Como se puede apreciar, el procedimiento de inserción consulta a la función colaLlena, función que tiene
la responsabilidad de informar el estado de saturación de la cola, para agregar un nuevo dato o elemento,
de lo contrario, lanza la excepción de OVERFLOW (Overflow es un término muy utilizado en la
computación e informática, y tiene relación con el desbordamiento de un objeto o lógica).

La función que retornará la cantidad de elementos de una cola, en esta implementación, contiene un
cálculo que se basa en el valor posicional de la variable fin + 1 (puesto que el primer elemento es 0),
pero sustrayendo el valor de frente, lo cual responde al hecho de que la función debe cumplir con la
característica indeterminística (que toda pieza de software debe respetar) y considerar que al quitar
elementos la variable frente obviamente se incrementa.

public int cantElementos(){


return fin + 1 - frente;
}

Para informar del dato que va a salir, o que le corresponde ser atendido, escribiremos la función
frenteCola, la cual se hará cargo de aquello procurando no caer en la excepción de intentar informar un
valor si la cola se encuentra vacía:

public int frenteCola() throws Exception {


if (!colaVacia()) {
return listaCola[frente];
} else throw new Exception("Cola vacía ");
}

Para quitar elemento(s) de la Cola, escribimos el procedimiento quitar, el cual se hace cargo también de
comprobar que la cola no esté vacía y se describe como sigue:

Pág. 19
Módulo: 2
Curso: Estructura de datos

public int quitar() throws Exception {


if (!colaVacia()) {
return listaCola[frente++];
}else
throw new Exception("Cola vacía ");
}

Finalmente, si se requiere borrar los elementos de una cola, un sencillo procedimiento tendrá esa
responsabilidad:

public void borrarCola() {


frente = 0;
fin = -1;
}

3.2 Aplicación de una cola en un problema práctico


Queda como análisis y reflexión por parte suya respecto de la eficiencia del procedimiento.

Pues bien, explicados cada procedimiento y funciones de la clase, estamos en condiciones de resolver
problemas que tienen relación con las prioridades y el orden de llegada, al menos hasta ahora con
estructuras estáticas. Sin embargo, surge una duda muy razonable:

¿Qué sucede si tengo un arreglo de 5 elementos, y en mi programa invoco 5 veces al procedimiento


insertar, dos veces al procedimiento quitar, y vuelvo a invocar al procedimiento insertar?

La respuesta es simple, al volver a invocar al procedimiento insertar, me aparece un mensaje de “overflow”


impidiéndome agregar otro elemento.

¿Por qué? Porque la implementación carece de algún procedimiento que reordene los elementos y
permita la reubicación de los marcadores para la reutilización de los espacios.

Lo anterior es un problema que no tiene fácil salida, utilizando la misma implementación, porque de
contar con procedimientos de reordenación de los elementos, se arriesga la pérdida de la capacidad de
cómputo de la máquina, debido a los tiempos que ésta tardará en ejecutar la reordenación.

Pág. 20
Módulo: 2
Curso: Estructura de datos

Cierre
En el presente capítulo, analizamos diferentes conceptos más avanzados de Java como las clases,
métodos y atributos, que nos permiten entonces realizar la creación de estructuras de tipo colas. Todo
esto aplicado en un ejemplo de creaciones de estudiantes con sus respectivas notas.

Se hizo evidente las limitaciones de la implementación del TDA basada en arreglos, teniendo presente
que es plausible su uso de acuerdo con el contexto.

Dado lo anterior, se hizo la transformación de la lógica y de las reglas del TDA, incorporando nuevas
lógicas que permitieron optimizar la implementación basada en estructura estática y se logró hacer el
tratamiento de la cola como una cola circular.

Pudimos revisar también diferentes operaciones con colas, como corroborar si una cola está vacía o llena,
y con eso poder entonces decidir si es posibles realizar inserciones y/o eliminaciones en la misma.

Es importante, entonces, que podamos diferenciar de manera correcta entre listas y colas. Para poder
determinar cuál de estos algoritmos será el que dé mejor solución a un problema planteado. Entendiendo
una lista como una estructura más flexible, pero ante cierta problemática la estructura de tipo cola nos
puede entregar mayor eficiencia en tiempos de ejecución del algoritmo.

En el siguiente módulo revisaremos una nueva estructura de datos conocida como pila, donde veremos
que tienen una forma diferente de inserción y eliminación de datos.

Referencias bibliográficas
Sánchez Allende, J. (2009). Programación en JAVA (3a. ed.). Madrid, Spain: McGraw-Hill España. Pág 97 –
118.

Zohonero Martínez, I. y Joyanes Aguilar, L. (2008). Estructuras de datos en Java. Madrid etc, Spain:
McGraw-Hill España. Pág 319 – 332.

Pág. 21

También podría gustarte