Академический Документы
Профессиональный Документы
Культура Документы
PILAS, COLAS Y DOBLE COLA (STACK, QUEUE, DQUEUE). En programación, el uso de listas
es una práctica tan extendida que lenguajes tales como (por ejemplo) Java, Python y C++
soportan los mecanismos necesarios para trabajar con estructuras de: Vectores, Pilas, Colas,
Listas, etc. En C++, los programadores que usen Dev-Cpp ( Bloodshed.software -Dev-C++ ) pueden
aprovechar las ventajas que ofrecen las STL (Standard Templates Libraries) dentro de la cual se
pueden encontrar plantillas para la manipulación de listas tales como: Vectores, Listas, Sets,
Maps, etc. Por otro lado, los usuarios de Borland C++ (Turbo C++ versión 1.01) pueden hacer uso
de la CLASSLIB, misma que posee las librerías para los propósitos mencionados.
Nota: En las siguientes secciones se presentarán seis programas, tres para simular listas basadas
en arreglos estáticos y tres para simular listas por medio de enlaces dinámicos (punteros). En
cuanto al material incluido se debe hacer las siguientes declaraciones:
Para cada una de las clases creadas en los programas se han elegido nombres en inglés. La
idea es que gran parte de la documentación e implementación referente a listas está en dicho
idioma, así, se le da al estudiante la idea básica de como operar con las librerías soportadas por
los compiladores Dev-Cpp, Borlan C++, y otros.
Igual, se debe observar que los métodos de las clases tienen nombres en inglés, y que con
el objetivo de establecer cierta estandarización todas las clases poseen los mismos métodos,
aunque cada una de ellas implementa los mismos a su manera.
Pilas o Stacks: Una PILA es una estructura en donde cada elemento es insertado y retirado del
tope de la misma, y debido a esto el comportamiento de una pila se conoce como LIFO (último
en entrar, primero en salir).
Un ejemplo de pila o stack se puede observar en el mismo procesador, es decir, cada vez
que en los programas aparece una llamada a una función el microprocesador guarda el estado de
ciertos registros en un segmento de memoria conocido como Stack Segment, mismos que serán
recuperados al regreso de la función.
Llenando la pila.
SP
|
SP
|
push('A');
| | | | | A | después de haber agregado el primer elemento
...
SP
|
Vaciando la pila.
SP
|
Pop();
| | D | C | B | A | después de haber retirado un elemento
...
SP
|
Nota: observe que al final la lista está vacía, y que dicho estado se debe a que el puntero está al final de la pila y no al
hecho de borrar físicamente cada elemento de la pila.
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
#include <iostream>
using namespace std;
class Stack {
public:
// constructor
Stack() {
sp = STACK_SIZE-1;
items = 0;
itemsize = 1;
}
// destructor
~Stack() {};
int get()
{
if ( ! empty() ) {
sp ++;
items --;
}
return pila[sp];
}
// Probando la pila.
// Nota: obseve cómo los elementos se ingresan en orden desde la A hasta la Z,
// y como los mismos se recuperán en orden inverso.
int main()
{
int d;
Stack s; // s es un objeto (instancia) de la clase Stack
// llenando la pila
for (d='A'; d<='Z'; d++) s.put(d);
// vaciando la pila
while ( s.size() ) cout << (char)s.get() << " ";
Uno de los puntos más destacables en cuando al uso de listas enlazadas dinámicamente es el
hecho de crear estructuras conocidas como nodos. Un nodo es una especie de eslabón (similar al
de una cadena de bicicleta), es decir, cada nodo se enlaza con otro a través de un puntero que
apunta a una estructura del mismo tipo que el nodo. Por ejemplo, para crear una estructura de
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
nodo para almacenar enteros y a la vez para apuntar a otro posible nodo podemos emplear la
sintaxis:
struct nodo {
int data;
nodo *siguiente;
};
Observe que con la declaración anterior estamos creando el tipo estructurado nodo,
mismo que posee a los miembros: data para guardar valores enteros, y siguiente para apuntar o
enlazar a un supuesto siguiente nodo.
Ya que las listas dinámicas inicialmente se encuentran vacías, y más aún, una lista dinámica no
posee una dirección establecida en tiempo de compilación ya que las dirección de memoria que
ocupará cada uno de los elementos se establecerá en tiempo de ejecución, entonces cómo
determinar la condición de vacío ?. En nuestro ejemplo usaremos un contador (ITEMS) que dicho
sea de paso, si ITEMS = 0, entonces la lista está vacía. (la condición de vacío también podría
determinarse al verificar el SP, es decir, si el SP = NULL, significa que la lista no posee elementos
).
Al hacer un análisis previo de los eventos que acontecerán en la pila y su puntero de lectura y
escritura (SP, que en esta ocasión es una estructura tipo nodo), se tiene lo siguiente:
1) Al principio la lista está vacia, en ese caso el SP es igual a NULL y, en consecuencia, el puntero
next también es NULL.
SP = NULL
/*---------------------------------------------------------------+
+ Ejemplo de una pila (STACK) enlazada dinámicamente +
++
+ Autor: Oscar E. Palacios +
+ email: oscarpalacios1@yahoo.com.mx +
++
+ Manifiesto: +
+ Este programa puede distribuirse, copiarse y modificarse de +
+ forma libre. +
+---------------------------------------------------------------*/
#include <iostream>
//#include <conio.h>
class StackDin {
// atributos
int ITEMS; /* número de elementos en la lista */
int ITEMSIZE; /* tamaño de cada elemento */
nodo *SP; /* puntero de lectura/escritura */
public:
// constructor
StackDin() : SP(NULL), ITEMS(0), ITEMSIZE(sizeof(DATA_TYPE)) {}
// destructor
~StackDin() {}
nodo *temp;
temp->data = valor;
temp->next = SP;
SP = temp;
ITEMS ++;
return valor;
}
int empty() { return ITEMS == 0; }
d = SP->data;
temp = SP->next;
if (SP) delete SP;
SP = temp;
ITEMS --;
return d;
}
StackDin s;
DATA_TYPE d;
while ( ! s.empty() )
cout << (DATA_TYPE)s.get() << " ";
cin.get();
return 0;
}
Colas o Queues
Una cola sencilla es una estructura en donde cada elemento es insertado Inmediatamente
después del último elemento insertado; y donde los elementos se retiran siempre por el frente
de la misma, debido a esto el comportamiento de un una cola se conoce como FIFO (primero en
entrar, primero en salir).
Cuando en el teclado se oprime una tecla, el código del carácter ingresado es trasladado y
depositado en un área de memoria intermedia conocida como "el buffer del teclado", para esto
el microprocesador llama a una rutina específica. Luego, para leer el carácter depositado en el
buffer existe otra función, es decir, hay una rutina para escribir y otra para leer los caracteres del
buffer cada una de las cuales posee un puntero; uno para saber en dónde dentro del buffer se
escribirá el siguiente código y otro para saber de dónde dentro del buffer se leerá el siguiente
código.
Llenando la cola.
cola
|
| | | | | | al principio
|
cabeza
cola
|
put('A');
| A | | | | | después de haber agregado el primer elemento
|
cabeza
...
cola
|
|
cabeza
Vaciando la cola.
cabeza
|
cabeza
|
get();
| A | B | C | D | | después de haber retirado un elemento
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
...
cabeza
|
al final
| A | B | C | D | | después de haber retirado todos los elementos
|
cola
Obsérvese que al final el cabeza apunta hacia el mismo elemento que la cola, es decir, la cola
vuelve a estar vacía. Puesto que la cola que estamos proyectando reside en un arreglo estático
los componentes del arreglo aún están dentro de la misma, salvo que para su recuperación se
debería escribir otro método. En una cola dinámica (como se demostrará más adelante) los
elementos retirados de la misma se eliminan de la memoria y podría no ser posible su
recuperación posterior.
Nota: En el programa que aparece en seguida, al tipo de lista implementado por la clase Queue
se le conoce como "lista circular" debido al comportamiento de sus punteros. Es decir si los
métodos para escribir o leer detectan que el puntero correspondiente ha sobrepasado el tamaño
máximo de elementos permitidos dentro de la cola, éste es puesto a cero.
/*---------------------------------------------------------------+
+ Ejemplo de una cola (QUEUE) basada en un arreglo estático +
++
+ Autor: Oscar E. Palacios +
+ email: oscarpalacios1@yahoo.com.mx +
++
+ Manifiesto: +
+ Este programa puede distribuirse, copiarse y modificarse de +
+ Forma libre. +
+---------------------------------------------------------------*/
#include <iostream.h>
class Queue {
public:
// constructor
Queue() {
cabeza = 0;
cola = 0;
ITEMS = 0;
ITEMSIZE = 1;
}
// destructor
~Queue() {}
// probando la cola
int main()
{
int d;
Queue q;
while ( q.size() ) {
cout << (char)q.get() << " ";
}
/*---------------------------------------------------------------+
+ Ejemplo de una cola (QUEUE) basada en un arreglo dinámico +
++
+ Autor: Oscar E. Palacios +
+ email: oscarpalacios1@yahoo.com.mx +
++
+ Manifiesto: +
+ Este programa puede distribuirse, copiarse y modificarse de +
+ forma libre. +
+---------------------------------------------------------------*/
#include <iostream>
struct nodo {
DATA_TYPE data;
nodo *next;
};
class QueueDin {
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
// atributos
int ITEMS, ITEMSIZE;
nodo *cola, *cabeza;
public:
// constructor
QueueDin() : cola(NULL), cabeza(NULL), ITEMS(0), ITEMSIZE(sizeof(DATA_TYPE)) {}
// destructor
~QueueDin() {}
ITEMS ++;
temp->data = valor;
temp->next = NULL;
if (cabeza == NULL)
{
cabeza = temp;
cola = temp;
} else
{
cola->next = temp;
cola = temp;
}
return valor;
}
d = cabeza->data;
temp = cabeza->next;
if (cabeza) delete cabeza;
cabeza = temp;
ITEMS --;
return d;
}
/* punto de prueba */
int main()
{
QueueDin s;
DATA_TYPE d;
// llenando la cola
for (d='A'; d<='Z'; d++) {
s.put(d);
cout << d << " ";
}
/*------------------------------------------------------------------+
+ Ejemplo de una cola doble (DQUEUE) basada en un arreglo est tico +
++
+ Autor: Oscar E. Palacios +
+ email: oscarpalacios1@yahoo.com.mx +
++
+ Manifiesto: +
+ Este programa puede distribuirse, copiarse y modificarse de +
+ Forma libre. +
+------------------------------------------------------------------*/
#include <iostream.h>
#include <mem.h> // por memmove
class SDQueue {
// atributos
int itemsize; // tamaño de cada elemento
int items; // número de elementos
int cola, cabeza; // punteros de lectura y escritura
almacen alma; // el almacen o arreglo
public:
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
// constructor
SDQueue() : cola(0), cabeza(0), items(0), itemsize(sizeof(DATA_TYPE)) {}
// destructor
~SDQueue() {}
/* punto de prueba */
int main()
{
SDQueue s;
DATA_TYPE d;
while ( ! s.empty() )
cout << (char)s.get_front() << " ";
struct nodo {
int data;
nodo *next, *prev;
};
Gráficamente podemos imaginar la estructura anterior como:
#include <iostream.h>
#include <conio.h>
struct nodo {
DATA_TYPE data;
nodo *next, *prev;
};
class DDqueue {
public:
// constructor
DDqueue() : cola(NULL), cabeza(NULL), items(0), itemsize(sizeof(DATA_TYPE)) {}
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
// destructor
~DDqueue() {}
temp->data = valor;
items ++;
if (cabeza == NULL )
{
temp->next = NULL;
temp->prev = NULL;
cabeza = temp;
cola = temp;
} else
{
cola->next = temp;
temp->prev = cola;
cola = temp;
cola->next = NULL;
}
return valor;
}
temp->data = valor;
items ++;
if (cabeza == NULL )
{
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
temp->next = NULL;
temp->prev = NULL;
cabeza = temp;
cola = temp;
} else
{
cabeza->prev = temp;
temp->next = cabeza;
cabeza = temp;
cabeza->prev = NULL;
}
return valor;
}
items --;
d = cabeza->data;
temp = cabeza->next;
if (cabeza) delete cabeza;
cabeza = temp;
return d;
}
items--;
d = cola->data;
temp = cola->prev;
Universidad Mariano Gálvez
Facultad de Ingeniería en Sistemas de Información
Cat. Ing. Ilonkka Carolina Cabrera Cintora
Curso: Programación I
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Estructuras_II
/* punto de prueba */
int main()
{
clrscr();
DDqueue s;
DATA_TYPE d;
// vaciando la lista
while ( ! s.empty() )
cout << (DATA_TYPE)s.get_front() << " ";