Está en la página 1de 53

Captulo XI: Colas

En ste capitulo hablaremos de una esructura muy utilizada e importante en el rea de laprogramacin, nos
referimos a las estructuras de datos tipo Colas.
Por ejemplo cuando mandamos a impresin un documento, ste acta en forma de cola, es decir; primera
en entrar, primera en salir, o por sus siglas en ingls (First in, first out), ya que el primer documento que
llega a la "Cola de Impresin", es el primer documento que es impreso.
Pero las colas, no slo son usadas por las impresoras, sino tambin en la vida cotidiana tienen otras muchas
aplicaciones, por ejemploel celular, cuando recibimos un mensaje de texto, ste es almacenado en un "lugar"
(dentro del chip) que se comporta como cola; otro ejemplo son las colas de tareas en la pc, las colas de
prioridades,etc.
Claro, estos ejemplosson muy complejos y exigen que tengamos conocimientos de sistemas operativos (uso
y creacin), por tanto y para resguardar nuestra salud mental, no vamos a entrar en tanto detalle respecto a
las aplicaciones complejas de las colas, sin embargo trataremos algunas abstracciones que nos ayudarn a
comprender el funcionamiento de sta estructura.
Concepto de Cola
Una cola, es una estructura en la cual se almacenan elementos (en orden de llegada), es decir que, se
ingresan los elementos por la parte final de la estructura y se eliminan (o se sirven) por la parte del frente.

Como puede observarse, sta estructura cuenta con dos apuntadores, uno que apunta al ltimo elemento y
otro que apunta hacia el primer elemeto (o el elemento del frente).
Se debe tener en cuenta que, una cola, almacena los datos en ella, manteniendo cierto orden, ya que sus
elementos se aaden por el final de la cola y se extraen o se eliminan por la parte de frente.
El lector dispernsar el por que la insistencia de ello, pero cuando uno inicia este estudio, al momento de
programar, se cunfe fcilmente, por que las sentencias de las funciones son muy parecidas a la de una pila, y
en algunas ocaciones me pasaba que empezaba programando una cola, pero terminaba funcionando como
pila.
Las operaciones con las colas son:
-insert (q, x) Inserta el elemento x en la parte posterior de la cola q
-remove(q) Suprime el elemento delantero de la cola q
-empty(q) Retorna True o false, si la cola tiene elementos o no.
Las colas pueden implementarse, al igual que las pilas, mediante dos formas:
Arrays
Memoria Dinmica
Tipo Cola Implementado como Arreglo

La figuara de arriba, muestra la forma de implementar una cola, como arreglo, en la que cada casilla,
representa una estructura compuesta por el tipo de dato a guardar (o bien otra estructura).
Las variables q.rear y q.front, se van modificando cada vez que aadimos o eliminamos datos de nuestra
cola.
Para determinar la cantidad de elementos en cualquier momento es:
Cant=q.rear-q.front+1
Ahora vemos un ejemplo del funcionamiento de las colas, implementadas como arreglos:
Supongamos que en una cola vamos a almacenar elementos de tipo carcter.
Insert(&q, A);

q.rear=0, q.front=0
insert (&q, B)

q.rear=1
q.front=0
insert (&q, C);

q.rear=2
q.front=0
remove(&q);

q.rear=2
q.front=1
remove(&q);

q.rear=2
q.front=2
insert(&q, D);

C D

0 1 2 3 4
q.rear=3
q.front=2
insert(&q, E);

q.rear=4
q.front=2
Como se puede ver, al manejar una cola en forma de arreglolineal, resulta complicado y poco eficiente, por
que al eliminar elementos quedan nodos vacos y cuando se llega al ltimo elemento de la cola, aparecer un
mensaje de error, (o al menos debera aparecer), que indioque que ya no hay ms espacios, sin embargo, eso
sera una total mentira, ya que tenemos elementos sin utilizar; una solucin para ello podra ser que cada
vez que se eliminen un elemento mover todos los datos hacia la izquierda, pero, te imaginas la cantidad
de cdigo para realizar esa accin???... eso es muy complejo (y no resuelve el problema de la eficiencia),
entonces es donde surge, el considerar la cola, como un arreglo circular.


Pero como puede verse, el manero de los subndices, resulta bastante complejo, poco accesible y, tampoco se
resuelve el problema de la eficiencia; es decir que sta solucin tampoco resulta eficiente para el problema
que se intenta resolver, por esas consideraciones no trataremos acerca de esta estructura, en forme de
arreglo, por que no nos resulta viable, nos concentraremos en la implementacin,
usando memoriadinmica, la cual, si resulta ms eficiente y hasta cierto punto menos compleja.
Colas implementadas con Memoria Dinmica
Para hacer uso de las colas, debemos declarar el nodo y los apuntadores de la cola, as:
typedef struct _nodo {
int dato;
struct _nodo *siguiente;
} tipoNodo;
typedef tipoNodo *pNodo;
typedef tipoNodo *Cola;
Donde, es evidente que, tipoNodo es el tipo de los nodos que compondrn la cola.
pNodo es el tipo para declarar punteros a un nodo.
Cola es el tipo para declarar colas

Las operaciones, siguen siendo las mismas:
Aadir
Eliminar
Algoritmo Para Aadir elementos en la cola
Si la cola est vaca:
2. Puntero primero y puntero ltimo deben apuntar a NULL
3. Creamos el nuevo nodo (con ayuda de malloc() )
4. Luego la parte siguiente del nuevo nodo, debe apuntar a NULL
5. Tanto, primero y ultimo deben apuntar, al nuevo nodo.

Si la cola, tiene elementos:
6. Creamos el nuevo nodo, ya sea en la misma funcin o con ayuda de otra funcin
7. Hacemos que la parte siguiente del nodo apunte a NULL
8. Luego, la parte siguiente de ultimo, deba apuntar al nodo
9. Y ultimo, ahora debe apuntar al nodo.
Algoritmo Para eliminar
10. Guardar el elemento dato nodo en una variable temporal
11. colocar un apuntador temporal hacia el nodo primero de la cola
12. cambiar el puntero (hacia el nodo) primero, hacia el nodo hacia el cual apunta el nodo, que estaba al
frente de la cola
13. si despus de eso el apuntador primero es NULL entonces no hay ms datos en la cola y el apuntador
ultimo tambin debe apuntar a NULL
14. Liberar memoria apuntada por el apuntador temporal
15. devolver el valor guardado en la variable temporal

Ejemplo 11.1
Se desea almacenar cierto nmero de enteros en una estructura de tipo Cola, disee una solucin que
permita, leer, eliminar datos de la cola.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

/*declaracion de la cola*/
struct nodo
{
int elemento;
struct nodo *siguiente;
};
typedef struct nodo Nodo;
typedef struct
{
Nodo *frente;
Nodo *final;
}Cola;
/*declaracion de las funciones*/
void CrearCola(Cola *cola);
void insert (Cola *cola, int x);
int remover(Cola *cola);
int empty(Cola cola);
main()
{
int x, opc=8, j=0;
Cola cola;
CrearCola(&cola);
clrscr();
while(opc!=3)
{
printf("\t\t\tMENU PRINCIPAL\n\n\n");
printf("\t 1. Insertar\n");
printf("\t 2. Eliminar\n");
printf("\t 3. Salir\n");
scanf("%d", &opc);
switch(opc)
{
case 1: printf("Ingrese el numero a introducir:\n");
scanf("%d", &x);
insert(&cola, x);
++j;
break;
case 2: printf("%d fue eliminado de la cola\n", remover(&cola));
--j;
getch();
break;
}
clrscr();
}
getch();
return 0;
}
/*definicion de las funciones*/
void CrearCola(Cola *cola)
{
cola->frente=cola->final=NULL;
}
/*funcion que inserta el dato en la parte final de la cola*/
void insert (Cola *cola, int x)
{
Nodo *nuevo;
nuevo=(Nodo*)malloc(sizeof(Nodo));
nuevo->elemento=x;
nuevo->siguiente=NULL;
if(empty(*cola))
{
cola->frente=nuevo;
}
else
cola->final->siguiente=nuevo;
cola->final=nuevo;
}
/*elimina el elemento que esta aL frente de la cola*/
int remover (Cola *cola)
{
int temp=NULL;
if(!empty(*cola))
{
Nodo *nuevo;
nuevo=cola->frente;
temp=cola->frente->elemento;
cola->frente=cola->frente->siguiente;
free(nuevo);
}
else
printf("ERROR, cola vacia, se puede eliminar\a\n");
return (temp);
}
int empty(Cola cola)
{
return (cola.frente==NULL);
}
Explicacin
Como puede notarse, hemos implementado, de una manera muy sencilla, los algoritmos para ingresar y
eliminar datos en una cola, note que hemos declarado dos estructuras para la cola, es decir que, una de ellas
contiene la parte entera de los datos que vamos a guardar y el apuntador hacia el siguiente nodo; mientras
que la otra estructura, cuenta con los apuntadores del frente y del final.
Algo importante que hay que resaltar es el hecho que, en la zona de declaracin de variables, debemos
declarar la varible de tipo Cola que es el parmetro que le pasaremos a las diferentes funciones; muchas
veces se nos olvida hacer eso y por lo cual, intentamos, erradamente, mandarle ladireccin del tipo de dato,
es decir; que en vez de mandarle la direccin de la variable cola (&cola), le mandamos la direccin del TAD
Cola (&Cola), lo cual no sera correcto.
Apartir de ello, creamos la cola, como lo explicamos, haciendo que cola->frente=cola->final=NULL; con lo
cual nos aseguramos que la cola est vaca, y lista para agregar valores. Las dems funciones, slo son la
implementacin rigurosa de los algoritmos planteados con anterioridad.
No es importante aprenderse al pi de la letra, cada una de las funciones, ya sea para la pila o para las colas,
si no que, es importante, aprenderse lo que hace cada funcin, tener presente el algoritmo e implementarlo
segn convenga al problema que estamos resolviendo.
Ejemplo 11.2
Cree una cola en C, que permita introducir y realizar un suceso por el usuario, el cual debe ser una arreglo
unidimensional; sin embargo, la cola debe ser implementada dinmicamente.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct datos elemento;
struct datos {
char suceso[81];
elemento *siguiente;
};
void error (void)
{
printf("Error, insufuciente espacio en memoria\n\a");
exit(1);
}
elemento *nuevoelemento (void)
{
elemento *q=(elemento*)malloc(sizeof(elemento));
if(!q)error();
return q;
}
void menu (void);
void introducir (elemento**, elemento**, char[]);
char *realizar (elemento**, elemento**);
main()
{
elemento *principio, *final;
char opcion, suceso[81];
principio=final=NULL;
while(1){
do{
clrscr();
menu();
opcion=toupper(getche());
}while(opcion!='I' && opcion !='R' && opcion != 'S');
clrscr();
switch(opcion){
case 'I': printf("\nIntroduzca un suceso:\n");
gets(suceso);
introducir(&principio, &final, suceso);
break;
case 'R': strcpy(suceso, realizar(&principio, &final));
if(*suceso)
printf("\realizando el suceso %s", suceso);
printf("Pulse una tecla para continuar:\n");
getch();
break;
case 'S': exit(0);
}
}
}
void menu(void)
{
printf("\n\tIntroducir suceso");
printf("\n\t realizar el suceso");
printf("\n\t salir");
printf("\n\t elija la opcion deseada (I, R, S)");
}
/*A$adir a la cola */
void introducir (elemento **p, elemento **f, char suceso[])
{
elemento *pc, *fc, *q;
pc=*p; /*principio de la cola */
fc=*f; /*final de la cola */
q=nuevoelemento();
strcpy(q->suceso, suceso);
q->siguiente=NULL;
if(fc==NULL)
pc=fc=q;
else
fc=fc->siguiente=q;
*p=pc;
*f=fc;
}
/*Recuperar dato de la cola */
char *realizar (elemento **p, elemento **f)
{
elemento *pc, *fc, *q;
char *suceso;
pc=*p; /*principio de la cola */
fc=*f; /*final de la cola*/
if(pc!=NULL)
{
q=pc;
suceso=(char*)malloc(strlen(q->suceso)+1);
strcpy(suceso, q->suceso);
pc=pc->siguiente;
if(pc==NULL)
fc=NULL;
free(q);
*p=pc;
*f=fc;
}
else
{
printf("no hay sucesos\n\n\a");
suceso[0]='\0';
}
return suceso;
}
Cuestionario
16. Por qu las Colas se consideran estructuras del tipo
FIFO?__________________________________________________________________
______________________________________________________________________
_____
17. Cules son las diferencias entre Pilas y
Colas?_________________________________________________________________
____________________________________________________________
18. En informtica, cules son las aplicaciones de las
Colas?_________________________________________________________________
____________________________________________________________
19. Mencione y explique las formas en las que podemos implementar las estructuras tipo
Cola:__________________________________________________________________
______________________________________________________________________
________________________________________________________
20. Puede una cola, en algn momento comportarse como una Pila?Por qu? Mencione al menos un
ejemplo:________________________________________________________________
______________________________________________________________________
______________________________________________________________________
___________________________________________________
Ejercicios
21. Escribir un programa en C, que lea cierca cantidad de enteros y luego determine: Cul es el valor
mayor, el valor menor y el promedio de todos los datos.
22. Disee un programa que sea capaz de leer dos colas y mediante un mensaje indicar si son iguales.
Nota: los elementos constitutivos de las colas son caracteres.
23. En un supermercado, se tiene slo una caja habilitada para que los clientes puedan cancelar
sus compras, se pide que, el sistema muestren la cantidad de productos comprados, el monto total de
la venta.
24. Una tienda dispone de 10 repartidores, para las entregas a domicilio, genere un programa que simule:
el despacho de cada repartidor, sabiendo que si la entrega se realiza despus de 30 minutos de
realizada la orden, al cliente se le aplica un 30% sobre la compra. El programa debe mostrar: el total
de entregas por repartidor, el monto de la ganancia, y las prdidas, en concepto de entregas tardas.
25. En la empresa "La Bodeguita", se lleva el control de los inventarios, por el mtodo PEPS, (Primeros en
entrar, Primeros en Salir). Y se desea mecanizar este proceso, para ello, se deben ingresar los
productos, y para registrar la venta, se necesitan los siguientes datos: Cdigo, correlativo de
orden, descripcin, cantidad y precio. El sistema debe generar: el informe de todas la ventas, el
artculo que ms se ha vendido, y el que menos, as como la ganancia de la empresa.
Identifique, y corriga, los posibles errores que estn presentes en las siguientes funciones:
int empty(Cola cola)
{
return (cola.frente);
}
Nodo *CrearNodo(int x)
{
aux=(Nodo*)malloc(sizeof(Cola));
aux->elemento=x;
aux->siguiente=NULL;
return aux;
}
Captulo XII: Listas Enlazadas
En muchos cursos, libros y Manuales, inician el estudio de las Estructuras de Datos Dinmicas, hablando
acerca de las Listas, sin embargo, stemanual ha sido la excepcin, ya que considero que, el estudio de las
listas, posterior al conocimiento y manejo de las Pilas y Colas, se hace mucho ms comprensible.
Concepto de Lista Enlazada
Es una coleccin de elementos dispuestos uno detrs del otro, en la que cada elemento se conecta al
siguiente por un "Enlace" o "Puntero".

Como se observa en la imagen, los nodos de las listas al igual que las colas y pilas, est compuesta por una
parte de informacin (que pude ser datos enteros, flotantes, caracteres, estructuras..) y el puntero que
mantiene el enlace entre un nodo y otro.
Existen varios tipos de Listas, pero para efectos de comprensin y sintetizacin, hablaremos de cutro tipos
esenciales de listas:
Tipos De Listas
26. Lista simplemente enlazada: Cada nodo, contiene un nico apuntador hacia el siguiente nodo, por lo
cual hace de l una estructura muy eficiente, ya que el ltimo de la lista apunta hacia null, por ello, es
fcil hacer recorridos directos.

27. Listas Doblemente enlazada: Esta lista se caracteriza por que sus nodos contienen dos punteros, uno
hacia el nodo siguiente y otro hacia el nodo anterior.

28. Listas Circulares: Este tipo de lista, es slo una extencin de las lista simplemente enlazada, con la
diferencia que el ltimo elemento se enlaza al primer elemento de la lista, lo cual permite el recorrido
en forma de anillo

29. Lista Circular Doblemente enlazada: Quiz este tipo de lista, sea la ms compleja, ya que es la
combinacin de las lista circular y las doblemente enlazadas, ya que es una lista doblemente enlazada
donde el primer elemento se conecta con el ltimo y viceversa.

Ahora el lector comprende, el por que, si hablamos de estos tpicos al inicio, a lomejor, hubiera
desistido de leer ste manual, y es que, al tener la experiencia de haber trabajado con estructuras
como pilas y colas, antes de listas, hace que uno comprenda mucho mejor, los conceptos y
algoritmos de ste tipo de estructuras.
El TAD Lista
En una lista podemos almacenar datos del mismo tipo, con la caracterstica que puede contener un
nmero indeterminado de elementos y que, mantienen un orden explcito, por que cada elemento,
se une a otro mediante un puntero, como ya se ha dicho anteriormente, los elementos constitutivos
de las listas se denominan nodos.
Las listas son estructuras de datos dinmicos, por tanto, pueden cambiar de tamao durante la
ejecucin del programa, aumentando o disminuyendo el nmero de nodos.
Un aspecto importante de las listas es que las inserciones, las podemos hacer por el frente, al final,
en medio, despus de..., etc, etc, etc; es decir que, no existen reglamentos que nos restringan
aadir datos a una lista, en la posicin que nosotros querramos.
De igual manera, para las eliminaciones de nodos, podemos hacerlo como nosotros lo querramos,
si embagargo, se acostumbra ingresando el campo de informacin o dato que se desea eliminar.
Operaciones con las listas
P: puntero a un nodo
L: puntero a la lista
ListaVacia(L): Iniciliza la lista L, como lista vaca
empty(L): determina si la lista est vaca o no
Insertar(L, x, p): Inserta al dato x, en un nuevo nodo de la lista L, despus del nodo apuntado
por p
eliminar(L, x): elimina, de la lista L, el nodo que contiene a x
Nodo(p): Hace referencia la nodo que apunta p
Info(p): hace referencia al info del nodo
next(p): siguiente direccin si p no es NULL
Info(next(p)): info del nodo que sigue a nodo (p) en la lista
Se puede decir que, estas son las operaciones bsicas para una lista; sin embargo, como ya se ha
insistido, eso depender del programador y de la complejidad del problema que se est
resolviendo, adems del tipo de lista que se haya elegido.
Para ello, acontinuacin hablaremos, por separado, de cada uno de los tipos de listas.
Listas Simplemente Enlazadas

Una estructura como sta, requiere, que se tengan en cuenta, las operaciones bsicas que, se
realizarn:
Estructura del Nodo
Por ejemplo, la podemos definir as:
struct nodo{
int x;
struct nodo *sig;
};
typedef struct nodo *Lista; /* Sinnimo para el tipo de dato*/
Lista p; /* Aqu guardaremos la direccin del primer nodo */
p=getnodo();
Funcin getnodo()
Esta funcin, se utiliza para pedirle memoria a la computadora, lo cual puede realizarse en las
misma funcin de insertar, pero para tener un mekor orden, es mejor hacerlo por aparte.
Por tanto, es evidente que, sta funcin lo que devuelve es una direccin de memoria.
Lista getnodo()
{
Lista p;
p=(Lista)malloc(sizeof(struct nodo));
return p;
}
Lo que devuelve, es la direccin del nuevo nodo, que se guard, en la variable p.
Funcin Insertar despus del nodo apuntado por p
Las inserciones en las Listas, no siempre se hacen al principio (pila) o al final (como las colas), las
listas nos permiten insertar, entre dos nodos, por ejemplo en una lista, tenemos: B, Q, M, Y D. Y
queremos insertar el elemento E, entre Q y M:

El algoritmo sera el siguiente:
30. Si P apunta a NULL, mostrar un mensaje de error y terminar la ejecucin.
31. sino, genere otro puntero, q, en el cual guarde la informacin.
32. luego, la parte siguiente del nuevo nodo, debe apuntar a al siguiente nodo, del apuntado por P.
33. p->siguiente, debe apuntar al nuevo nodo .
el cdigo, sera as:
void insafter (Lista p, char x)
{
Lista q;
If(p==NULL)
Printf("Error, lista vaca\a\n");
Else
{
q=getnode();
q->x=x;
q->sig=p->sig;
p->sig=q;
}
}
Funcin Borrar despus de...
sta funcin es muy similar a la funcin de eliminar de las pilas y colas, con la diferencia que debemos
enlazar el nodo anterior con el siguiente nodo:

Algoritmo:
34. Crear un nodo auxiliar apuntado por q.
35. si p, apunta a nullo p->sig apunta a NULL, imprima mensaje de error
36. sino; q, en suparte de siguiente, debe tener la direccin a la que apuntaba, p->sig.
37. p->sig debe apuntar a q en su parte de siguiente.
38. Liberar de memoria el nodo apuntado por q.
void delafter(Lista p, char *px)
{
Lista q;
If(p==NULL || p->sig==NULL)
Printf("ERROR, lista vaca\a\n");
Else
{
q->sig=p->sig;
p->sig=q->sig;
free(q);
}
}
Funcin de Lista Vaca
Int empty(Lista p)
{
int r;
if(p==NULL)
r=1;
else
r=0;
return r;
}
/* Para limpiar la lista*/
void limpiar (Lista L)
{
L=NULL;
}
Con sta funcin, lo que hacemos es inicializar la lista a NULL, por lo que se pierden los elementos que
habamos guardado en los nodos. Pero Ojo, eso no significa que hayamos liberado memoria que ocuparon,
los nodos, esa memoria ser liberada, cuando se deje de ejecutar el programa, o si hubisemos, utilizado la
funcin free(), para cada nodo.
Funcin Buscar
sta funcin, nos devuelve, la direccin de memoria de un valor que deseamos buscar en la lista.
Lista buscar(Lista frente, char x)
{
/* frente: puntero que indica la cabeza de una lista.
X: carcter que deseamos buscar
*/
Lista dir;
For(dir=frente; dir!=NULL; dir=dir->sig)
If(x==dir->x)
Return dir;
Return NULL;
}
Ejemplo 12.1
Se pide que, cree una agenda, donde pueda almacenar el nombre, telfono y correo electrnicode sus
amigos; hacindo uso de una lista enlazada. Dicha agenda, debe permitirle: aadir un nuevo registro,
eliminar y Mostrar la lista de todos los registros.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct nodo{
int corre;
char nom[80];
char tel[9];
char email[50];
struct nodo *sig;
};
typedef struct nodo *Lista;
Lista p, cabeza;
Lista getnodo();
void insafter(Lista p, char nom[80], char tel[9], char email[50], int i);
void eliminar (Lista p, int k);
void imprimir(Lista p);
main()
{
char nom[80], tel[9], email[50];
int k, opc=8, i=0;
clrscr();
p=getnodo();
cabeza=p;
while(opc!=4)
{
printf("\t\t\nMENU PRINCIPAL\n\n\n");
printf("\t\t1. Registrar Nuevos Datos\n");
printf("\t\t2. Imprime todos los registros\n");
printf("\t\t3. Eliminar Datos\n");
printf("\t\t4.Salir\n");
scanf("%d", &opc);
switch(opc)
{
case 1: printf("Ingrese el Nombre:");
scanf("%s", &nom);
printf("Telefono:");
scanf("%s", &tel);
printf("e-mail:");
scanf("%s", email);
i++;
insafter(&p, nom, tel, email, i);
break;
case 2: printf("Listado de todos los registros\n\n");
imprimir(&p);
break;
case 3: printf("A quien desea eliminar?(ingrese el correlativo)\n");
scanf("%d", &k);
eliminar(&p, k);
break;
}
clrscr();
}
return 0;
}
Lista getnodo()
{
Lista p;
p=(Lista)malloc(sizeof(struct nodo));
if(p==NULL)
printf("Memoria Insuficiente\a\n");
return p;
}
void insafter(Lista p, char nom[80], char tel[9], char email[50], int i)
{
Lista q;
if(p==NULL)
printf("ERROR, lista vaca\n\a");
else
{
q=getnodo();
strcpy(q->nom, nom);
strcpy(q->tel, tel);
strcpy(q->email, email);
q->corre=i;
q->sig=p->sig;
p->sig=q;
p=p->sig;
}
}
void imprimir(Lista p)
{
Lista dir;
p=p->sig;
for(dir=p; dir!=NULL; dir=dir->sig)
{
printf("\n\t***********************************\n");
printf("\t correlativo: %d\n", dir->corre);
printf("\t Nombre %s\n", dir->nom);
printf("\t Telefono: %s\n", dir->tel);
printf("\t e-mail: %s\n", dir->email);
printf("\n\t***********************************\n");
getch();
}
}
void eliminar(Lista p, int k)
{
Lista indice;
cabeza=p;
for(indice=cabeza; indice!=NULL; indice=indice->sig)
{

if(indice->corre==k)
{
cabeza=cabeza->sig;
printf("%s est hiciendo eliminado\n", indice->nom);
getch();
if(p==NULL || p->sig==NULL)
printf("ERROR, ya no hay m s datos\n");
else
{
cabeza->sig=indice->sig;
free(indice);
}
}
}
}
Listas Doblemente Enlazadas

Hata ahora, los recorridos que hemos realizado en las listas; han sido en sentido directo, pero existen
muchos casos en los que es necesario acceder a los elementos de las estructuras en ambos sentidos (adelante
y por detrs), de ah es donde se deriva la importancia de esta estructura.
La declaracin de la estructura puede ser:
typedef struct nodo{
int elemento;
struct nodo *sig, *ant
}Lista;
/*Note la declaracin de dos punteros, uno hacia el nodo siguiente
y el otro hacia el nodo anterio
*/
typedef Lista *tPosicion;
typedef Lista *tLista
Las operaciones bsicas, siguen siendo las mismas; aunque clara con sus variantes, por que recordemos que,
en ste tipo de estructuras estamos manejando dos punteros, en un solo nodo.
Insertar
Para insertar en un lista, existen algunos mecanismos, casos, formas, etc.
Por ejemplo:
INSERTAR AL FRENTE DE LA LISTA
39. si lista est vaca
1. Crear un nuevo nodo
2. Asignar el valor a la parte dato del nodo
3. Hacer que nuevo nodo, en su parte de anterior apunte a NULL
4. Y en su parte de siguiente a la lista
5. El puntero del elemento de l frente de la lista, debe apuntar al nuevo nodo.
40. si la lista No est vaca
0. Agregar un nuevo nodo
1. Asignar el valor a la parte dato del nodo
2. Hacer que nuevo nodo, en su parte de anterior apunte a NULL
3. El nuevo nodo en su parte de siguiente, debe apuntar al primer elemento de la lista
4. Si la Lista!=NULL, entonces Lista->ant=p
5. Luego el apuntador a la lista (Lista), debe apuntar al nuevo nodo.
Void inserfrente (tPosicion Lista, int x)
{
tPosicion p;
if(empty==1)
{
p=getnodo();
p->elemento=x;
p->ant=NULL;
p->sig=Lista;
Lista=p;
}
else
{
p=getnodo();
p->elemento=x;
p->ant=NULL;
p->sig=Lista;
if(Lista!=NULL)
Lista->ante=p;
Lista=p;
}
}
INSERTAR AL FINAL DE LA LISTA
Para hacer este tipo de operacin, necesitamos un puntero (q), que apunte al ltimo elemento de la lista.
El algoritmo sera, entonces, el siguiente:
41. Crear el nuevo nodo
42. hacer que p->elemento, sea igual al valor
43. hacemos que p->ant apunte al ultimo nodo
44. p->sig ser igual a lo que tenga q->sig
45. q->sig debe apuntar al nuevo nodo
void inserfinal (tPosicion q, int valor)
{
tPosicion p;
p=getnodo();
p->elemento=valor;
p->ant=q;
p->sig=q->sig;
q->sig=p;
}
Funcin getnodo()
tLista getnodo()
{
tLista nuevo;
nuevo=(tLista)malloc(sizeof(Lista));
if(nuevo==NULL)
printf("Memoria insuficiente\a\n");
nuevo->sig=nuevo->ant=NULL;
return nuevo;
}
Funcin Eliminar
Esta funcin, se encarga de borrar, el nodo apuntado por "p", encontrado con la funcin posicin y
considere eliminacin al inicio, en medio y al final.
Algoritmo:
46. Busque el nodo que contiene el dato que desea eliminar , teniendo el cuidado de guardar la direccin
del nodo a eliminar y la direccin del nodo anterior a ste.
47. la parte siguiente del nodo anterior debe apuntar al puntero sifguiente del nodo a eliminar.
48. la parte anterior del nodo siguiente a eliminar debe apuntar a la parte a lo que apuntaba la parte
anterior del nodo a eliminar.
49. en caso de que el nodo a eliminar sea el primero en la lista, se modifica la cabeza para que tenga la
direccin del nodo siguiente.
50. finalmente liberamos la memoria ocupada.
Void eliminar (tPosicion Lista, int x)
{
tPosicion actual;
int encontrado=0;
actual=Lista;
/*empezamos a buscar el nodo*/
while((actual!=NULL) && (!econtrado))
{
encontrado=(actual->elemento==x);
if(!encontrado)
actual=actual->sig;
}
/*Enlazamos el nodo anterior con el diguiente nodo*/
if(actual!=NULL)
{
if(actual==Lista)
{
lista=actual->sig;
if(actual->sig!=NULL)
actual->sig->ant=NULL;
}
else if(actual->sig!=NULL) /*No es el ultimo nodo*/
{
actual->ant->sig=actual->sig;
actual->sig->ant=actual->ant;
}
else
actual->ant->sig=NULL;
free(actual);
}
}
Ejemplo 12.2
/*******************************************************************
* LISTA.C *
* Objetivo del programa: Realizar un programa que de de altas, *
* busque y liste una lista de tipo estructura dinamica *
* doblenmente ligada *
* Versin: 2.1 *
* Autor: JOSE LUIS SANCHEZ FERRUSCA *
* Fecha: 6/04/2005 *
*******************************************************************

/********************* Inclusin de libreras **********************/
#include <stdio.h>
#include <malloc.h>
/********************* Prototipos **********************************/
void altas(void);
void busqueda(void);
void listado(void);
void baja(void);
/********************* Variables Globales **************************/
struct lista *nuevo,*primero,*recorre, *anterior;
int i,op,num,bus,opcion;
typedef struct lista;
struct lista /* Crea una lista de tipo struct con dos campos, numero (entero) y sig (apuntador de tipo struct
lista)*/
{
int numero;
struct lista *sig, *ant;
};
void main()
{
op=1;
nuevo=NULL; /* El apuntador esta vacio */
primero=NULL; /* El apuntador esta vacio */
recorre=NULL; /* El apuntador esta vacio */
do
{
/* clrscr(); */
printf ("\n\n \t *********************************\n");
printf (" \t *** ***\n");
printf (" \t *** PROGRAMA DE ESTRUCTURAS ***\n");
printf (" \t *** ***\n");
printf (" \t *********************************\n");
printf (" \n\n\n \t 1.- ALTAS \n \t 2.- BUSQUEDA \n \t 3.- LISTADO \n\t 4.- Baja \n\t 5.- SALIR \n\n");
printf (" SELECCIONE UNA OPCION DEL MENU \n");
scanf ("%d",&opcion);
switch(opcion)
{
case 1: altas();
break;
/*case 2: busqueda();
break;*/
case 3: listado();
break;
case 4: baja();
break;
}
}while (opcion!=5);
scanf ("\n");
}
/********************* Declaracion de Funciones ********************/
/********************************************************************
* Funcin:Alta *
* Argumentos: void - No recibe argumentos *
* - * *
* Valor de Retorno: Void -> No regresa valores *
* Comentario: Esta funcin va a dar de alta los datos en la lista *
* *
********************************************************************/
void altas(void)
{
int flag;
nuevo=primero;
printf ("\n INGRESE EL NUMERO PARA DARLO DE ALTA\n ");
scanf ("%d",&num);
nuevo=malloc(sizeof(struct lista)); /* Busca un espacio de memoria del tamao de struct lista */
nuevo->numero=num; /* Vuevo en su campo numero asignale el valor de num */
nuevo->sig=NULL; /* Ya no hay ms espacios de memoria para ligar */
nuevo->ant=NULL;
recorre=primero;
if (primero==NULL)
{
primero=nuevo;
recorre=nuevo;
}
else
{
do
{
if (primero==recorre)
{
if (nuevo->numero<primero->numero)
{
primero=nuevo;
primero->sig=recorre;
recorre->ant=nuevo;
}
else
{
primero->sig=recorre;
recorre->ant=primero;
}
}
else if (recorre->sig!=NULL)
{
if (nuevo->numero<recorre->numero)
{
anterior=recorre->ant;
nuevo->ant=anterior;
nuevo->sig=recorre;
anterior->sig=nuevo;
recorre->ant=nuevo;
}
}
else
{
recorre->sig=nuevo;
nuevo->ant=recorre;
}
}while(recorre!=NULL);
}
}
/********************************************************************
* Funcin: Busqueda *
* Argumentos: void - No recibe argumentos *
* - * *
* Valor de Retorno: Void -> No regresa valores *
* Comentario: Esta funcin va a hacer una busqueda en la lista *
* *
********************************************************************/
void busqueda()
{
int bus;
recorre=primero;
printf ("\nINGRESE EL NUMERO A BUSCAR\n");
scanf ("%d",&bus);
do
{
if (bus==recorre->numero) /* El dato a buscar se encuentra en recorre en su campo numero ?*/
{
printf ("\n SE HA ENCONTRADO EL NUMERO %d\n ",bus);
recorre=recorre->sig;
}
else
recorre=recorre->sig;
}while (recorre!=NULL);
}
/********************************************************************
* Funcin: listado *
* Argumentos: void - No recibe argumentos *
* - * *
* Valor de Retorno: Void -> No regresa valores *
* Comentario: Esta funcin va a imprimir la lista *
* *
********************************************************************/
void listado()
{
recorre=primero;
while (recorre!=NULL)
{
printf ("\n NUMERO--> %d\n",recorre->numero);
recorre=recorre->sig;
}
}
/********************************************************************
* Funcin:Baja *
* Argumentos: void - No recibe argumentos *
* - * *
* Valor de Retorno: Void -> No regresa valores *
* Comentario: Esta funcin va a dar de baja los datos en la lista *
* *
********************************************************************/
void baja()
{
recorre=primero;
anterior=primero;
printf ("\nINGRESE EL NUMERO A BUSCAR\n");
scanf ("%d",&bus);
do
{
if (bus==recorre->numero) /* El dato a buscar se encuentra en recorre en su campo numero ?*/
{
if (recorre==nuevo)
{
nuevo=nuevo->ant;
free(recorre);
nuevo->sig=NULL;
}
else if (primero!=recorre) /* Estan primero y recorre en la misma posicin? */
{
anterior->sig=recorre->sig;
free(recorre);
recorre=anterior->sig;
recorre->ant=anterior;
else
{
anterior->sig=recorre->sig;
recorre=anterior->sig;
free(primero);
primero=recorre;
anterior=primero;
}
}
else
if (recorre==primero)
recorre=recorre->sig;
else
{
recorre=recorre->sig;
anterior=anterior->sig;
}
}while (recorre!=NULL);
}
NOTA: Este cdigo ha sido elaborado por JOSE LUIS SANCHEZ FERRUSCA, aunque, por razones
de didctica, he hecho algunas modificaciones.
Listas Circulares

Se puede afirmar que, las listas circulares, son un caso especial de las listas simples, con la variante que el
ltimo nodo, en su parte de siguiente, apunta al primer nodo de la lista.
La parte de dato, de la lista circular, puede estar compuesta de enteros, punto flotante, caracteres, arreglos o
estructuras.

Declaracin de la estructura
Typedef struct elemento{
Int dato;
Struct nodo*sig;
}nodo;
typedef nodo* lc;
lc *Lista=NULL;
Funcin getnodo()
lc getnodo()
{
lc nuevo;
nuevo=(lc)malloc(sizeof(nodo));
nuevo->dato=x;
nuevo->sig=nuevo;
/* para que sea circular debe apuntar a s mismo*/
return nuevo;
}
Funcin Ingresar
Void insertar (lc *Lista, int x)
{
lc p;
p=getnodo(x);
if(*Lista==NULL) /*si hay elementos en la lista*/
{
p->sig=(*Lista)->sig;
(*Lista)->sig=p;
}
*Lista=p;
}
Funcin Eliminar
ste algoritmo es muy parecido al de una lista simple, ya que sta estructura, como ya se ha dicho, es un
caso especial de la lista lineal, sin embargo, existen unas pequeas consideraciones a tener en cuenta.
Algotitmo
51. Se debe buscar el nodo que contiene el dato que desea eliminar
52. luego se debe enlazar el nodo anterior con el siguiente
53. si el nodo a eliminar est apuntado por "Lista", es decir el puntero de acceso, se modifica "Lista" para
que contenga la direccin del nodo anterior a ste.
54. finalmente se libera el nodo de la memoria
void eliminar (lc *Lista, int x)
{
lc *actual;
int encontrado=0;
if((*Lista)==NULL)
printf("No hay elementos en la lista\n");
else
{
actual=*Lista;
/*empezamos a buscar*/
while((actual->sig!=Lista) && (!encontrado))
{
encontrado=(actual->sig->dato==x);
if(!encontrado)
actual=actual->sig;
encontrado=(actual->sig->dato==x);
/*enlazamos el nodo abterior con el nodo siguiente*/
if(encontrado)
{
lc=p;
p=actual->sig; /*nodo a eliminar*/
if(*Lista==(*Lista)->sig)
*Lista=NULL;
else
{
if(p==*Lista)
*Lista=actual;
actual->sig=p->sig;
}
free(p);
}
}
}
Ejemplo 12.3
Las reglas de la divisibilidad indican que, si un nmero termina en cero o cifra par, es divisible por dos; y si
la suma de sus elementos es tres o mltiplo de tres, entonces, ese nmero es divisible por tres. Adems que,
si un nero es divisible por dos y por tres al mismo tiempo, entonces es divisible por seis. (ejemplo 12.
Termina en cifra par, 2+1=3, es divisible por 2 y por tres, entonces tambin es divisible por 6), disee un
programa que, que almacene en una lista circular, y muestre por cual de esos tres nmeros (2 , 3 y 6) es
divisible.
/*Ejemplo de listas *.C*/
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
typedef struct elemento{
int x;
struct elemento *sig;
}nodo;
typedef nodo* lc;
lc *Lista;
int k=0;
void inser (lc *Lista, int x);
void divi(lc* Lista);
main()
{
int num[80], pos=0, i=0;
clrscr();
printf("\t\t\tINGRESE EL NUMERO:\n\n\n");
while((num[pos++]=getchar())!='\n');
num[--pos]='\0';
for(i=0; i<pos; i++)
inser(Lista, num[i]);
divi(Lista);
getch();
return 0;
}
void inser(lc *Lista, int x)
{
lc nuevo;
nuevo=(lc)malloc(sizeof(nodo));
nuevo->x=x;
nuevo->sig=nuevo;
if(*Lista!=NULL)
{
nuevo->sig=(*Lista)->sig;
(*Lista)->sig=nuevo;
}
*Lista=nuevo;
k++;
}
void divi (lc *Lista)
{
int div2=0, div3=0, sum=0, i=1;
lc aux;
aux=(*Lista)->sig;

while(i<=k)
{
sum=sum+aux->x;
aux=aux->sig;
i++;
}
if(sum%3==0)
{
div3=1;
printf("El numero es divisible entre tres\n");
}
aux=(*Lista);
if(aux->x%2==0)
{
div2=1;
printf("El numero es divisible entre Dos\n");
}
if(div2==1 && div3==1)
printf("Tambien es divisible entre 6\n");
getch();
}
Explicacin
Lo primero que hacemos, es almacenar el nmero en un arreglo, auxiliar, ya que cada elemento del nmero
lo guardamos en una casilla del arreglo, luego, vamos pasando cada nmero como parmetro a la funcin
insert(), ya que en ella creamos los nodos y en s, la lista circular. Una vez que, hemos llenado la lista,
pasamos el puntero de acceso a la funcin divi(), en la cual determinamos los nemeros por los cuales es
divisible.
Listas Circulares Doblemente Enlazadas

ste tipo de listas, es una combinacin de las listar cicular y la lista doblemente enlazada, puesto que cada
nodo est conectado con el siguiente nodo y el anterior a l, adems que el primer nodo est conectado al
ltimo, y el ltimo al primero.
Es por esa razn que, particularmente consideto que, sta estructura es una de las ms complejas de
manejar, por las consideraciones que debemos tener.
Declaracin de la estructura
Typedef struct celda{
Int elemento;
Struct nodo*sig, ant;
}tipocelda;
typedef tipocelda *tPosicion;
typedef tipocelda* tLista;
Funcin getnodo()
tLista getnodo()
{
tLista L;
L=(tLista)malloc(sizeof(tipocelda));
If(L==NULL)
Printf("ERROR: Memoria Insuficiente\a\n");
L->sig=L->ant=L;
Return L;
}
Funcin Insertar
Algoritmo:
55. Crear el nuevo nodo
56. Guardar el dato en el nuevo nodo
57. Hacer que el nuevo nodo, en su parte de siguiente apunte al nodo anterior (que est siendo apuntado
por p)
58. Luego copiar en nuevo->ant, lo que hay en p->ant
59. hacer que en la parte de siguiente del nodo anterior apuntado por p, contenga la direccin del nuevo
nodo
60. hacer que p->ant apunte anuevo
61. guardar la direccin de nuevo en p
void insertar (int x, tPosicion p)
{
tPosicion nuevo;
nuevo=(tPosicion)malloc(sizeof(tipocelda));
if(nuevo==NULL)
printf("ERROR: memoria insuficiente\a\n");
nuevo->elemento=x;
nuevo->sig=p;
nuevo->ant=p->ant;
p->ant->sig=nuevo;
p->ant=nuevo;
p=nuevo;
}
Funcin Buscar
Esta funcin recibe como argumento un dato a buscar, dentro de la lista y devuelve el nodo que contenga
dicho dato.
tPosicion buscar (int x, tLista L)
{
tPosicion p;
int ban=0;
p=L->sig;
while((p!=L) && (!ban))
if(p->elemento==x)
ban=1;
else
p=p->sig;
return p;
}
Ejemplo 12.4
Disee una lista circular doblemente enlazada, que gaurde enteros, y luego permita determinar cuantas
veces se encuentra un nmero ingresado por el usuario.
#include <stdio.h>
#include <conio.h>
#include <string.h>
/*Version Circular doblememente enlazada*/
typedef struct tipoNodo{
int x;
struct tipoNodo *adelante;
struct tipoNodo *atras;
}Nodo;
/*Declaracion de los sinonimos para referirnos al tipo de dato*/
typedef Nodo *tLista;
typedef Nodo *tPosicion;
int cont=0;
/*Declaracin de las funciones que utilizaremos*/
void insertarPrim (tLista cabeza, int entrada);
tLista CrearNodo();
void ImprimeLista(Nodo *ptr);
int buscar(int busca, Nodo *cabeza, Nodo *ptr);
main()
{
/*inicio del programa principal*/
Nodo *ptr;
tPosicion cabeza;
int entrada, opc, busca;
char ban;
/*cabeza contiene la direccin del primer nodo creado*/
cabeza=CrearNodo();
ban='S';
clrscr();
printf("\n\n\n\n");
printf("\n\t
");
printf("\n\t ");
printf("\n\t PROGRAMA QUE CALCULA LOS VALORES REPETIDOS EN UNA LISTA ");
printf("\n\t DOBLEMENTE ENLAZADA ");
printf("\n\t ");
printf("\n\t
");
while(ban=='S' || ban=='s')
{
printf("\n\nIngrese un elemento para la lista:\n");
scanf("%d", &entrada);
cont++;
/*le enviamos a la funcion de insertar, le enviamos la direccin del
primer nodo y el valor que vamos a introducir*/
insertarPrim(cabeza, entrada);
printf("Desea Introducir un nuevo elemento a la lista? (S/N)\n");
ban=getch();
}
printf("Los Valores Guardados en la Lista son:\n");
/*la funcion de imprimir, recibe un puntero hacia el primer
nodo para iniciar con la impresion*/
clrscr();
ImprimeLista(cabeza);
getch();
clrscr();
printf("\n\t\tQue desea Hacer?\n");
printf("\t\t1.Buscar un valor en la lista\n");
printf("\t\t2.Salir\n");
scanf("%d", &opc);
switch(opc)
{
case 1:clrscr();
printf("Ingrese el valor que desea buscar en la lista:\n");
scanf("%d", &busca);
printf("El valor %d se encuentra %d veces en la lista\n\n", busca,buscar(busca,cabeza, cabeza));
break;
case 2:exit(1);
default:printf("Error, el comando no es v lido\n");
break;
}
getch();
return 0;
}
/*definicin de las funciones*/
void insertarPrim(tPosicion cabeza, int entrada)
{
tPosicion nuevo;
/*creamos un nuevo nodo y le asignamos la direccion de memoria*/
nuevo=(tPosicion)malloc(sizeof(Nodo));
if(nuevo==NULL)
printf("ERROR\n");
nuevo->x=entrada;
/*la parte de adelante del nuevo nodo, apunta al primer nodo*/
nuevo->adelante=cabeza;
nuevo->atras=cabeza->atras;
cabeza->atras->adelante=nuevo;
cabeza->atras=nuevo;
}
tLista CrearNodo()
{
/*creamos un nuevo nodo, el cual sera la "cabeza" de la lista*/
tLista L;
L=(tLista)malloc(sizeof(Nodo));
if(L==NULL);
printf("Error, memoria Insuciente\n");
L->adelante=L->atras=L;
return L;
}
void ImprimeLista(Nodo *ptr)
{
Nodo *p;
int k=0;
if(ptr!=NULL)
{
printf("Lista de Nmeros Guardados:\n");
p=ptr->adelante;
do{
k++;
if(k<=cont)
printf("\t\t\t* %d *\n", p->x);
p=p->adelante;
}while(p!=ptr->adelante);
}
else
{
printf("No Hay elementos en la Lista\n");
}
}
int buscar(int busca, Nodo *cabeza, Nodo *ptr)
{
int k=0;
if(ptr!=NULL)
{
cabeza=ptr->adelante;
do{
if(cabeza->x==busca)
k++;
cabeza=cabeza->adelante;
}while(cabeza!=ptr->adelante);
}
else
{
printf("No Hay elementos en la Lista\n");
}
return k;
}
Cuestionario
62. Qu son y para que sirven las
listas?__________________________________________________________________
______________________________________________________________________
_______________________________________________
63. Cul es la diferencia entre una lista circular y una doblemente
enlazada?_______________________________________________________________
______________________________________________________________________
_____________________________________________
64. Una lista, Puede comportarse como una
cola?__________________________________________________________________
______________________________________________________________________
_______________________________________________
65. Por qu se afirma que una lista circular, no tiene ni primer y ltimo
elemento?_______________________________________________________________
______________________________________________________________________
_____________________________________________
66. La funcin getnodo() e insertar(), se diferencian
en:____________________________________________________________________
______________________________________________________
Ejercicios
67. En una lista simple, que almacena enteros, mostrar cual es el dato mayor y cual es el dato menor.
68. Disee un registro para n alumnos de una Universidad, con sus respectivas notas de Programacion II y
Estructuras de Datos, dichos datos, se deben guardar en una Lista lineal. Se sabe que, en sta
universidad, existe la poltica que si, un alumno ha reprodado estas dos materias, es dado de baja en la
universidad. (Nota mnima 6.00)
69. Se desea guardar cierta cantidad de caracteres en una lista doble, y luego imprimir los caracteres de
izquierda a derecha y viceversa.
70. Disee un programa que, le permita al usuario, almacenar en una lista doblemete enlazada, los
registros de las personas que han adquirido un seguro de vida, adems que permita eliminar registros,
y adicionar nuevos datos.
71. En una lista circular se desean guardar, cadenas de caracteres, y luego imprimir la cadena de mayor
longitud.
72. Disee un programa queopere con nmeros complejos (tienen parte real e imaginaria), y permita,
sumarlos, restarlos, multiplicarlos, y determinar la magnitud de cada uno de ellos.
73. Escribir un programa en C, que apartir de una lista doble circular, ordene alfabticamente, los
caracteres contenidos en ella y luego los imprima.
74. Disee un programa en C, que contenga una lista circular, cuyos elementos sean enteros largos, luego
imprimir todos los elementos y la suma de ellos.
75. El aeropuerto internacional de El Salvador, desea controlar el flujo de pasajeros, y de aerolneas que
circulan por l. Disee un programa que de soporte a las salidas y entradas de los aviones, mediante
una lista doblemente enlazada cuya informacin sera la siguiente: Destino, compaa, hora de salida y
pasajeros. Luego, y apartir de ese ltimo dato, es que se eliminarn los datos de la lista de pasajeros.
76. Un punto en el espacio, est compuesto por coordenadas x, y, z. Disee un programa que apartir de
una lista circular doble, determine la distancia entre el primer punto y el ltimo. (Nota: D
2
=(x1-
x2)
2
+(y1-y2)
2
+(z1-z2)
2
).
Nota Final
Del lenguaje C, hace falta por hablar mucho, con estas insignificantes pginas, no he agotado el estudio de
ste interesante y til, lenguaje de programacin. Sin embargo, yo concluyo hasta aqu, por que algunas
cosas ya no me compete, hablarlas a m.
No me queda mas que, desearte suerte, en sta etapa como programador.
Y nimo!!! Sigue siempre adelante....
Recuerda que puedes hacer cualquier comentario, sugerencia, observacin, etc, a mi correo electrnico:
memeboi27[arroba]hotmail.com
Bibliografa
-"Aprenda Lenguaje ANSI C Como si estuviera en Primero". De jaln de la Fuente, Javier Garca. Rodriguez
Garrido, Jos Ignacio. EscuelaSuperior de Ingenieros Industriales, Universidad de Navarra. 1998
-"Curso de C". Urrutia, Gorka. http://www.elrincondelc.com
-"Introduccin al Lenguaje de Programacin C/C++". Pacho, Sergio.
-"Ejercicios de Practicas de C". Ledesma Muoz, Fernando. http://ledesma.f2o.org
-"Curso de armado y reparacin de PC en 10 clases. Primera Parte". Boselli, Gustavo.
gb100m[arroba]yahoo.com
-"Tutorial sobre apuntadores y arreglos en C". Jensen, Ted. Ao 2000. http://www.
netcom.com/~tjensen/ptr/cpoint.htm
-"Algoritmos y Estructuras de Datos, una perspectiva en C". Joyanes Aguilar, Luis. Zahonero Martnez,
Ignacio. Mc Graw Hill, ao 2004. Madrid,Espaa.
-"Estructuras dinmicas de datos algoritmos, acceso, propiedades, ejemplos". Pozo, Salvador. Julio de 2001.
http://www.conclase.net/c/edd/
-"Guines de Clase: Introduccin a la Informtica, programacin I y Programacin II". Gonzlez, Csar.
Castillo, Milagro. Vzquez, Rodrigo, (Respectivamente). Universidad de El Salvador, Facultad
de Ingeniera y Arquitectura, Escuela de Sistemas Informticos.

Pilas o Stacks[editar]
Una PILA es una estructuras en donde cada elemento es insertado y retirado
del tope de la misma, y debido a esto el comportamiento de un 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 funcin el microprocesador guarda el estado de ciertos registros en un
segmento de memoria conocido como Stack Segment, mismos que sern recuperados al regreso de la
funcin.
Pila en arreglo esttico[editar]
En el programa que se ver en seguida, se simula el comportamiento de una estructura de pila. Aunque en el
mismo se usa un arreglo esttico de tamao fijo se debe mencionar que normalmente las implementaciones
hechas por fabricantes y/o terceras personas se basan en listas dinmicas o enlazadas.
Para la implementacin de la clase Stack se han elegido los mtodos:
put(), poner un elemento en la pila
get(), retirar un elemento de la pila
empty(), regresa 1 (TRUE) si la pila esta vacia
size(), nmero de elementos en la pila
El atributo SP de la clase Stack es el puntero de lectura/escritura, es decir, el
SP
indica la posicin dentro de la pila en donde la funcin put() insertar el
siguiente
dato, y la posicin dentro de la pila de donde la funcin get() leer el
siguiente dato.
Cada vez que put() inserta un elemento el SP se decrementa.
Cada vez que get() retira un elemento el SP se incrementa.

En el siguente ejemplo se analiza lo que sucede con el SP (puntero de pila) cuando se guardan en la pila uno
por uno los caracteres 'A', 'B', 'C' y 'D'. Observe que al principio el SP es igual al tamao de la pila.

Llenando la pila.
SP
|
+---+---+---+---+---+
| | | | | | al principio (lista vacia)
+---+---+---+---+---+
SP
|
+---+---+---+---+---+ push('A');
| | | | | A | despus de haber agregado el primer elemento
+---+---+---+---+---+
...
SP
|
+---+---+---+---+---+
| | D | C | B | A | despus de haber agregado cuatro elementos
+---+---+---+---+---+

Vaciando la pila.
SP
|
+---+---+---+---+---+ pop();
| | D | C | B | A | despus de haber retirado un elemento
+---+---+---+---+---+
...
SP
|
+---+---+---+---+---+
| | D | C | B | A | despus de haber retirado todos los elementos
+---+---+---+---+---+
Nota: observe que al final la lista est vacia, y que dicho estado se debe a que
el puntero est al final de la pila y no al hecho de borrar fsicamente cada
elemento
de la pila.

Ejemplo: Pila basada en un arreglo esttico
#include <iostream>
using namespace std;

#define STACK_SIZE 256 /* capacidad mxima */
typedef char arreglo[STACK_SIZE];

class Stack {

int sp; /* puntero de lectura/escritura */
int items; /* nmero de elementos en lista */
int itemsize; /* tamao del elemento */
arreglo pila; /* el arreglo */

public:
// constructor
Stack() {
sp = STACK_SIZE-1;
items = 0;
itemsize = 1;
}

// destructor
~Stack() {};

/* regresa el nmero de elementos en lista */
int size() { return items; }

/* regresa 1 si no hay elementos en la lista, o sea, si la lista est
vacia */
int empty() { return items == 0; }

/* insertar elemento a la lista */
int put(char d)
{
if ( sp >= 0) {
pila[sp] = d;
sp --;
items ++;
}
return d;
}

/* retirar elemento de la lista */
int get()
{
if ( ! empty() ) {
sp ++;
items --;
}
return pila[sp];
}

}; // fin de clase Stack


// probando la pila.
// Nota: obseve cmo los elementos se ingresan en orden desde la A hasta la Z,
// y como los mismos se recupern 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);

cout << "Items =" << s.size() << endl;

// vaciando la pila
while ( s.size() ) cout << (char)s.get() << " ";

cout << "\nPara terminar oprima <Enter>...";
cin.get();
return 0;
}
}

Pila dinmica[editar]
En el siguiente programa se presenta una implementacin de una estructura dinmica tipo pil a o stack. Es
importante hacer notar que, a diferencia de una pila basada en un arreglo esttico, una pila enlazadada
dinmicamente no posee de forma natural el mecanismo de acceso por ndices, en ese sentido, el
programador puede crear los algoritmos necesarios para permitir tal comportamiento. En la clase que
presentaremos en el ejemplo no se ha implementado el mecanismo de acceso por ndices, ya que la misma
se presenta como una alternativa para la simulacin de una pila o stack.
Uno de los puntos ms destacables en cuando al uso de listas enlazadas dinmicamente es el hecho de crear
estructuras conocidas como nodos. Un nodo es una especie de eslabn ( similar al de una cadena de bicicleta
), es decir, cada nodo se enlaza con otro a travs de un puntero que apunta a una estructura del mismo tipo
que el nodo. Por ejemplo, para crear una estructura de 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 declaracin 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 dinmicas inicialmente se encuentran vacias, y ms an, una lista dinmica no posee una
direccin establecida en tiempo de compilacin ya que las direccin de memoria que ocupar cada uno de los
elementos se establecer en tiempo de ejecucin, entonces cmo determinar la condicin de vacio ?. En
nuestro ejemplo usaremos un contador ( ITEMS ) que dicho sea de paso, si ITEMS = 0, entonces la lista est
vacia. ( la condicin de vacio tambin podra determinarse al verificar el SP, es decir, si el SP = NULL,
significa que la lista no posee elementos ).
Al hacer un anlisis previo de los eventos que acontecern en la pila y su puntero de lectura y escritura (SP,
que en esta ocasin 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 tambin es NULL.
SP = NULL

+------+------+
| ???? | next |--> NULL
+------+------+
2) Despus de agregar el primer elemento la situacin se vera as:
SP = asignado
1
+------+------+
| data | next |--> NULL
+------+------+
3) Despus de agregar otro elemento la situacin se vera as:
SP = asignado
2 1
+------+------+ +------+------+
| data | next |--> | data | next |--> NULL
+------+------+ +------+------+
Ejemplo: Pila basada en un arreglo dinmico
/*---------------------------------------------------------------+
+ ejemplo de una pila ( STACK ) enlazada dinmicamente +
+ +
+ 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>

using namespace std;

/* tipo de dato que contendr la lista */
typedef char DATA_TYPE;

// declaracin de estructura nodo
struct nodo {
DATA_TYPE data;
nodo *next;
};

class StackDin {

// atributos
int ITEMS; /* nmero de elementos en la lista */
int ITEMSIZE; /* tamao de cada elemento */
nodo *SP; /* puntero de lectura/escritura */

public:
// constructor
StackDin() : SP(NULL), ITEMS(0), ITEMSIZE(sizeof(DATA_TYPE)) {}

// destructor
~StackDin() {}

/* agregar componente a la lista */
DATA_TYPE put(DATA_TYPE valor)
{
nodo *temp;

temp = new nodo;
if (temp == NULL) return -1;

temp->data = valor;
temp->next = SP;
SP = temp;
ITEMS ++;
return valor;
}

int empty() { return ITEMS == 0; }


/* retirar elemento de la lista */
DATA_TYPE get()
{
nodo *temp;
DATA_TYPE d;

if ( empty() ) return -1;

d = SP->data;
temp = SP->next;
if (SP) delete SP;
SP = temp;
ITEMS --;
return d;
}

}; // fin de la clase StackDin


/* punto de prueba para la clase StackDin */
int main()
{
//clrscr();

StackDin s;
DATA_TYPE d;

for (d='A'; d<='Z'; d++) s.put(d);

while ( ! s.empty() )
cout << (DATA_TYPE)s.get() << " ";

cout << "\nPara terminar presione <Enter>...";
cin.get();
return 0;
}
Colas o Queues[editar]
Una cola sencilla es una estructura en donde cada elemento es insertado
inmediatamente despus 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).
Un ejemplo a citar de cola es el comportamiento del buffer del teclado.
Cuando en el teclado se oprime una tecla, el cdigo del carcter ingresado es trasladado y
depositado en una rea de memoria intermedia conocida como "el buffer del teclado", para esto
el microprocedador llama a una rutina especfica. Luego, para leer el carcter depositado en el
buffer existe otra funcin, 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 donde dentro del buffer
se escribir el siguiente cdigo y otro para saber de donde dentro del buffer se leer el siguiente
cdigo.
Cola en un arreglo esttico[editar]
En el programa que se ve en seguida, se simula el comportamiento de una estructura de cola
simple. Aunque en el mismo se usa un arreglo esttico de tamaoo fijo se debe mencionar que
normalmente las implementaciones hechas por fabricantes y/o terceras personas se basan en
listas dinmicas o dinamicamente enlazadas.
Para la implementacin de la clase Queue se han elegido los mtodos:
put(), poner un elemento en la cola
get(), retirar un elemento de la cola
empty(), regresa 1 (TRUE) si la cola est vacia
size(), nmero de elementos en la cola
El atributo cabeza de la clase Queue es el puntero de lectura.
El atributo cola de la clase Queue es el puntero de escritura.
Es decir, la cola indica la posicin dentro de la lista en donde la funcin put() insertar el
siguiente dato, y la cabeza indica la posicin dentro de la lista de donde la funcin get() leer el
siguiente dato.
Cada vez que put() inserta un elemento la cola se incrementa.
Cada vez que get() retira un elemento la cabeza se incrementa.
En el siguente ejemplo se analiza lo que sucede con la cola y la cabeza (punteros de escritura y
de lectura de la Lista) cuando se guardan en la cola uno por uno los caracteres 'A', 'B', 'C' y 'D'.
Observe que al principio: cola = cabeza = cero.

Llenando la cola.
cola
|
+---+---+---+---+---+
| | | | | | al principio
+---+---+---+---+---+
|
cabeza
cola
|
+---+---+---+---+---+ put('A');
| A | | | | | despus de haber agregado el primer elemento
+---+---+---+---+---+
|
cabeza
...
cola
|
+---+---+---+---+---+
| A | B | C | D | | despus de haber agregado cuatro elementos
+---+---+---+---+---+
|
cabeza
Vaciando la cola.
cabeza
|
+---+---+---+---+---+
| A | B | C | D | | antes de haber retirado elementos
+---+---+---+---+---+
cabeza
|
+---+---+---+---+---+ get();
| A | B | C | D | | despus de haber retirado un elemento
+---+---+---+---+---+
...
cabeza
|
+---+---+---+---+---+ al final
| A | B | C | D | | despus de haber retirado todos los elementos
+---+---+---+---+---+
|
cola
Observese que al final el cabeza apunta hacia el mismo elemento que la cola, es decir, la cola
vuelve a estar vacia. Puesto que la cola que estamos proyectando reside en un arreglo esttico
los componentes del arreglo an estn dentro de la misma, salvo que para su recuperacin se
debera escribir otro mtodo. En una cola dinmica (como se demostrar ms adelante) los
elementos retirados de la misma se eliminan de la memoria y podra no ser posible su
recuperacin 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
mtodos para escribir o leer detectan que el puntero correspondiente ha sobrepasado el
tamao mximo de elementos permitidos dentro de la cola, ste es puesto a cero.
Ejemplo: cola en un arreglo esttico
/*---------------------------------------------------------------+
+ ejemplo de una cola (QUEUE) basada en un arreglo esttico +
+ +
+ Autor: Oscar E. Palacios +
+ email: oscarpalacios1@yahoo.com.mx +
+ +
+ Manifiesto: +
+ Este programa puede distribuirse, copiarse y modificarse de +
+ forma libre. +
+---------------------------------------------------------------*/
#include <iostream.h>

#define MAX_SIZE 256 /* capacidad mxima */
typedef char almacen[MAX_SIZE];

class Queue {

int cabeza; /* puntero de lectura */
int cola; /* puntero de escritura */
int ITEMS; /* nmero de elementos en la lista */
int ITEMSIZE; /* tamao de cada elemento */
almacen alma; /* el almacen */

public:
// constructor
Queue() {
cabeza = 0;
cola = 0;
ITEMS = 0;
ITEMSIZE = 1;
}

// destructor
~Queue() {}

// regresa 1 (true) si la lista est vacia
int empty() { return ITEMS == 0; }

// insertar elemento a la lista
int put(int d)
{
if ( ITEMS == MAX_SIZE) return -1;
if ( cola >= MAX_SIZE) { cola = 0; }
alma[cola] = d;
cola ++;
ITEMS ++;
return d;
}

// retirar elemento de la lista
int get()
{
char d;
if ( empty() ) return -1;
if ( cabeza >= MAX_SIZE ) { cabeza = 0; }
d = alma[cabeza];
cabeza ++;
ITEMS --;
return d;
}

// regresa el nmero de elementos en lista
int size() { return ITEMS; }

}; // fin de la clase Queue


// probando la cola
int main()
{
int d;
Queue q;

for (d='A'; d<='Z'; d++) q.put(d);

cout << "Items = " << q.size() << endl;

while ( q.size() ) {
cout << (char)q.get() << " ";
}

cout << "\nPara terminar oprima <Enter> ...";
cin .get();
return 0;
}
Ejemplo: cola en un arreglo dinmico
/*---------------------------------------------------------------+
+ ejemplo de una cola (QUEUE) basada en un arreglo dinmico +
+ +
+ Autor: Oscar E. Palacios +
+ email: oscarpalacios1@yahoo.com.mx +
+ +
+ Manifiesto: +
+ Este programa puede distribuirse, copiarse y modificarse de +
+ forma libre. +
+---------------------------------------------------------------*/
#include <iostream>

using namespace std;

typedef char DATA_TYPE;

struct nodo {
DATA_TYPE data;
nodo *next;
};

class QueueDin {

// atributos
int ITEMS, ITEMSIZE;
nodo *cola, *cabeza;

public:
// constructor
QueueDin() : cola(NULL), cabeza(NULL), ITEMS(0),
ITEMSIZE(sizeof(DATA_TYPE)) {}

// destructor
~QueueDin() {}

/* agregar componente a la lista */
DATA_TYPE put(DATA_TYPE valor)
{
nodo *temp;

temp = new nodo;
if (temp == NULL) return -1;

ITEMS ++;
temp->data = valor;
temp->next = NULL;

if (cabeza == NULL)
{
cabeza = temp;
cola = temp;
} else
{
cola->next = temp;
cola = temp;
}
return valor;
}

// regresa 1 (true) si la lista est vacia
int empty() { return ITEMS == 0; }


/* retirar elemento de la lista */
DATA_TYPE get()
{
nodo *temp;
DATA_TYPE d;

if ( empty() ) return -1;

d = cabeza->data;
temp = cabeza->next;
if (cabeza) delete cabeza;
cabeza = temp;
ITEMS --;
return d;
}

}; // fin de la clase QueueDin

/* punto de prueba */
int main()
{
QueueDin s;
DATA_TYPE d;

// llenando la cola
for (d='A'; d<='Z'; d++) {
s.put(d);
cout << d << " ";
}

cout << endl;
// vaciando la cola
while ( ! s.empty() )
cout << (DATA_TYPE)s.get() << " ";

cout << "\nPara terminar presione <Enter>...";
cin.get();
return 0;
}

También podría gustarte