SlideShare una empresa de Scribd logo
1 de 26
Descargar para leer sin conexión
Estructuras dinámicas de Datos
Lenguaje C
Realizado por:
Carlos Ramses Garcia
01/05/2020
CONTENIDO
PILAS
Definición
Creación
Declaración
Uso
Manipulación a través de funciones
Ejemplo
COLAS
Definición
Creación
Declaración
Uso
Manipulación a través de funciones
Ejemplo
LISTAS
Definición
Creación
Declaración
Uso
Manipulación a través de funciones
Ejemplo
PILAS
Definición:
Una pila es una estructura de datos simple. Los datos se van apilando uno tras otro. Podemos
abstraer cada elemento como un nodo que puede apuntar a otro nodo.
Su modo de acceso es LIFO: el último en entrar es el primero en salir. Las operaciones que
tiene son 2: push y pop; la primera le pone un elemento y la segunda quita el último.
Declaración:
El Nodo:
Esto es de lo que estará compuesta nuestra pila, para ello usaremos una lista ligada en donde
un nodo apunta a otro y este otro a otro (opcionalmente), así infinitamente.
Claro que el elemento siguiente de un nodo es opcional; porque el elemento de hasta abajo no
apunta a nadie.
También tiene un nombre, que es el dato en sí que guardaremos en la pila. Si quisiéramos que
nuestra pila fuera de enteros entonces comenzaríamos cambiando el tipo de dato de char[] a
int.
El elemento superior:
En el inicio de todos los tiempos, debe haber un elemento superior aunque no tenga valor y no
apunte a nada. Es decir, aunque la pila esté vacía debemos tener un elemento que será el
inicio de todo:
Creación:
Agregar elementos a la pila: push
Veamos la operación push, que agrega un elemento a la pila.
El nodo superior es una variable global, por eso no necesitamos recibirla en la función.
Lo que hacemos es alojar espacio en memoria para almacenar nuestro nuevo elemento usado
memory allocate o malloc, como decidió bautizar esta función el gran Dennis.
A ese nuevo nodo le ponemos el dato que llevará (String), y como es el que estará hasta arriba
entonces hacemos que apunte hacia el que era el superior; y este nuevo ahora tomará su
lugar.
Explicado en otras palabras, este nuevo nodo será el superior y apuntará al que antes era el
superior; se está poniendo encima de él.
La próxima vez que apilemos, se creará otro nuevo y este dejará de ser el superior para pasar a
ser el siguiente del nuevo; y así sucesivamente.
Eliminar el último elemento (operación pop):
Esto es fácil pero interesante a la vez. Como vamos a desapilar el elemento, necesitamos hacer
que el elemento superior ahora sea al que apuntaba; es decir, su siguiente.
Pero eso no es todo, debemos liberar la memoria que se estaba usando y para ello
respaldamos lo que ocupaba el que vamos a eliminar dentro de temporal y llamamos a free.
Esto sólo ocurre en caso de que superior no sea nulo.
Uso:
-Apilar, también conocido como push: agregar un elemento
-Desapilar, o la operación pop: quitar el último elemento; es decir, el elemento superior
Manipulación a través de funciones:
-Imprimir: recorrer la pila e imprimir sus valores.
-Tamaño: devolver el tamaño de la pila.
-Leer último: leer el elemento superior de la pila.
-Vacía: indica si la pila está vacía.
Imprimir pila:
Imprimir la pila no es una operación necesaria, pero como este es un ejercicio sí lo haremos.
Únicamente recorremos toda la pila mientras haya un apuntador a siguiente:
Para esto necesitamos un nodo temporal y comenzamos recorriendo desde superior.
Asignamos a temporal lo que esté apuntando a siguiente; si ya no apunta a nada entonces
temporal será nulo y se terminará el ciclo.
Tamaño de pila o stack en C:
Esto es muy parecido al de imprimir; pero en lugar de imprimir vamos aumentando un
contador dentro del ciclo:
Comprobamos si superior es nulo y en caso de que sí ya no hacemos el ciclo, pues la pila está
vacía.
Operación top o peek de la pila(último elemento):
Esto es fácil, se lee el último elemento de la pila y en este caso es un String.
Si superior es nulo, se imprime que la pila está vacía.
En caso de que no, entonces devolvemos lo que tenga el elemento superior.
Método para saber si la pila está vacía:
podríamos decir que, si ya tenemos el método tamanio, podríamos regresar un booleano
resultante de la comparación de tamanio == 0 pero eso sería un desperdicio de recursos
Ya que si la pila tiene 0 elementos todo va bien, pero, ¿qué tal si la pila tiene 100000
elementos? tendríamos que recorrer todos dentro de tamanio para determinar al final que la
pila no está vacía.
Es por eso que mejor usamos otra lógica… si el elemento superior no apunta a nada, entonces
no hay más elementos y por lo tanto la pila está vacía.
Ejemplo:
Uniendo todo el código quedaría de esta manera:
#include <stdio.h> // printf
#include <stdlib.h> // malloc y free
#include <stdbool.h> // Booleanos
// Un nodo tiene un dato, el cual es el Nombre. Y otro nodo al que apunta
struct nodo {
char Nombre[45];
struct nodo *siguiente;
};
// Prototipos de funciones
void agregar(); // push
void eliminarUltimo(void); // pop
void imprimir(void);// Mostrar
int tamanio(void); // El tamaño de la pila
bool vacia(void); // Indica si la pila está vacía
void ultimo(void); // El último elemento.
// Todo comienza con el nodo superior
struct nodo *superior = NULL;
int main() {
int eleccion;
int Nombre1[45];
while (eleccion != 7) {
printf("nn--BIENVENIDO A LA PILA DEL ALMACEN--n1.- Agregar Objeton2.- Quitar
Objeton3.- Mostrar "
"pilan4.- Mostrar Cantidad de Objetos n5.- Comprobar si esta vacian6.- "
"Mostrar ultimo Objeton-7.- SalirnntElige: ");
scanf("%d", &eleccion);
switch (eleccion) {
case 1:
agregar();
break;
case 2:
eliminarUltimo();
break;
case 3:
imprimir();
break;
case 4:
printf("La pila tiene %d Objetosn", tamanio());
break;
case 5:
if (vacia()) {
printf("La pila esta vacian");
} else {
printf("La pila NO esta vacian");
}
break;
case 6:
ultimo();
break;
}
}
}
int tamanio(void) {
int contador = 0;
if (superior == NULL)
return contador;
struct nodo *temporal = superior;
while (temporal != NULL) {
contador++;
temporal = temporal->siguiente;
}
return contador;
}
bool vacia(void) { return superior == NULL; }
void ultimo() {
if (superior != NULL){
printf("El Ultimo Objeto es: %sn", superior->Nombre); }
else {
printf("La pila esta Vacia!!");
}
}
// Operación push
void agregar() {
// El que se agregará; reservamos memoria
nodo *nuevoNodo;
nuevoNodo =(struct nodo *) malloc(sizeof(struct nodo));
// Le ponemos el dato
printf("Ingresa el nombre del objeto:n");
scanf("%s",&nuevoNodo->Nombre);
printf("Agregando %s...n", nuevoNodo->Nombre);
// Y ahora el nuevo nodo es el superior, y su siguiente
// es el que antes era superior
nuevoNodo->siguiente = superior;
superior = nuevoNodo;
}
void imprimir(void) {
printf("Imprimiendo...n");
struct nodo *temporal = superior;
if(temporal == NULL){
printf("No hay objetos en la pila!!n");
}
while (temporal != NULL) {
printf("%sn", temporal->Nombre);
temporal = temporal->siguiente;
}
}
// Operación pop, eliminar el de hasta arriba
void eliminarUltimo(void) {
printf("Los trabajadores estan Quitando el Ultimo Objeto...n");
if (superior != NULL) {
// Para liberar la memoria más tarde debemos
// tener la referencia al que vamos a eliminar
struct nodo *temporal = superior;
// Ahora superior es a lo que apuntaba su siguiente
superior = superior->siguiente;
// Liberar memoria que estaba ocupando el que eliminamos
free(temporal);
}
}
COLAS
Definición:
Una cola es un tipo especial de lista enalazada en la que sólo se pueden insertar nodos en uno
de los extremos de la lista y sólo se pueden eliminar nodos en el otro. Además, como sucede
con las pilas, las escrituras de datos siempre son inserciones de nodos, y las lecturas siempre
eliminan el nodo leído. Este tipo de lista es conocido como lista FIFO (First In First Out), el
primero en entrar es el primero en salir.
Declaración:
El símil cotidiano es una cola para comprar, por ejemplo, las entradas del cine. Los nuevos
compradores sólo pueden colocarse al final de la cola, y sólo el primero de la cola puede
comprar la entrada. El nodo típico para construir pilas es el mismo que vimos en los capítulos
anteriores para la construcción de pilas: Los tipos que definiremos normalmente para manejar
colas serán casi los mismos que para manejar listas y pilas, tan sólo cambiaremos algunos
nombres:
Nodo es el tipo para declarar nodos, evidentemente.
Es evidente, que una cola es una lista abierta. Así que sigue siendo muy importante que
nuestro programa nunca pierda el valor del puntero al primer elemento, igual que pasa con las
listas abiertas. Además, debido al funcionamiento de las colas, también deberemos mantener
un puntero para el último elemento de la cola, que será el punto donde insertemos nuevos
nodos. Teniendo en cuenta que las lecturas y escrituras en una cola se hacen siempre en
extremos distintos, lo más fácil será insertar nodos por el final, a continuación del nodo que
no tiene nodo siguiente, y leerlos desde el principio, hay que recordar que leer un nodo
implica eliminarlo de la cola.
Creación:
Agregar Elementos A la Cola(Operación Enqueue):
Se llaman los datos extraidos a la función que creamos para crear la cola:
Lo que hacemos es alojar espacio en memoria para almacenar nuestro nuevo elemento usado
memory allocate o malloc, como decidió bautizar esta función el gran Dennis.
A ese nuevo nodo le ponemos el dato que llevará (el entero), y como es el que estará hasta
arriba entonces hacemos que apunte hacia el que era el superior; y este nuevo ahora tomará
su lugar, (Justo como en la pila).
Se limpia el buffer le almacenan los datos obtenidos en nodoNuevo->nombre y en
nodoNuevo->id para poderlos trabajar
Entonces si la cola está vacía el nodo toma el primer y último lugar si no entonces el ultimo
nodo se agrega el nodoNuevo toma el primer lugar para que después quede final apuntando
siguiente igualando a temporal.
Eliminar el Primer elemento (operación Dequeue):
Recordemos que leer un elemento de una cola, implica eliminarlo. Ahora también existen dos
casos, que la cola tenga un solo elemento o que tenga más de uno. Usaremos un puntero a un
nodo auxiliar:
Hacemos que nodo apunte al primer elemento de la cola, es decir a primero. Asignamos a
primero la dirección del segundo nodo de la pila: primero->siguiente. Guardamos el contenido
del nodo para devolverlo como retorno, recuerda que la operación de lectura en colas implica
también borrar. Liberamos la memoria asignada al primer nodo, el que queremos eliminar.
Leer un elemento en una cola con un solo elemento:
También necesitamos un puntero a un nodo auxiliar:
Hacemos que nodo apunte al primer elemento de la pila, es decir a primero. Asignamos NULL
a primero, que es la dirección del segundo nodo teórico de la cola: primero->siguiente.
Guardamos el contenido del nodo para devolverlo como retorno, recuerda que la operación
de lectura en colas implica también borrar. Liberamos la memoria asignada al primer nodo, el
que queremos eliminar. Hacemos que último apunte a NULL, ya que la lectura ha dejado la
cola vacía.
Leer un elemento en una cola, Caso general:
Hacemos que nodo apunte al primer elemento de la pila, es decir a primero. Asignamos a
primero la dirección del segundo nodo de la pila: primero->siguiente. Guardamos el contenido
del nodo para devolverlo como retorno, recuerda que la operación de lectura en colas implica
también borrar. Liberamos la memoria asignada al primer nodo, el que queremos eliminar.
Si primero es NULL, hacemos que ultimo también apunte a NULL, ya que la lectura ha dejado la
cola vacía.
Uso:
De nuevo nos encontramos ante una estructura con muy pocas operaciones disponibles. Las
colas sólo permiten añadir y leer elementos:
Añadir: Inserta un elemento al final de la cola. Leer: Lee y elimina un elemento del principio
de la cola.
Manipulación a través de funciones:
Con estas funciones getId() Y getpTrnom() lo que hicimos fue extraer cada dato por separado y
devolverlos para poder trabajarlos en la función enqueue();
Con la función isEmptywrap llamamos un valor que nos genera isEmpty() donde se verifica si
final está totalmente vacía retorna 1 por lo tanto imprimirá “la cola esta vacia!” si no el caso
contrario
Función donde se verifica si final esta vacío
Ejemplo:
Uniendo todo el código quedaría de esta manera:
#include <stdio.h>
#include <stdlib.h>
// Un nodo tiene un dato, el cual es el Nombre y el id. Y otro nodo al que apunta
struct persona {
int id;
char *nombre;
struct persona *siguiente;
};
int contador=0;
//Prototipos de funciones
char* getPtrNom();
int getId();
int isEmpty();
int menu();
void clearBuffer();
void dequeue();
void enqueue();
void isEmptyWrap();
typedef struct persona Nodo;
Nodo *final;
Nodo *inicio;
main() {
final = inicio = 0;
return menu();
}
int menu() {
char c;
printf("nn--Servitec c.a--n");
printf("nn-Cola para atender a los clientes-n");
do {
printf("n~~ MENU: cola! ~~");
printf("nHaga una seleccion:");
printf("n 1.-Ingresar a la cola (enqueue)");
printf("n 2.-Atender Cliente(dequeue)");
printf("n 3.-Cuantas personas hay en la cola?");
printf("n 4.-Comprobar si esta vacia(isEmpty)");
printf("n q: salir.n");
c = getchar();
switch(c) {
case '1':
enqueue();
break;
case '2':
dequeue();
break;
case '3':
printf(" Numero de Clientes en la cola: %d !n",contador);
break;
case '4':
isEmptyWrap();
break;
// default :
// printf(" Seleccione una de las opciones establecidas!");
// break;
}
} while(c != 'q' && c != EOF);
return 1;
}
// metodo wrapper para el menu
void isEmptyWrap() {
clearBuffer();
if (isEmpty()) {
printf("La Cola Esta Vacia!n");
} else {
printf("La Cola NO Esta Vacia!n");
}
}
int getId() {
int num;
printf("Ingrese el ID: ");
scanf("%d" , &num);
return num;
}
// retorna un nuevo puntero a un arreglo
char* getPtrNom() {
char d,*newAr;
int i = 0;
newAr = (char*) malloc(sizeof(char)*100);
printf("Ingrese el nombre: ");
while((d = getchar()) != EOF && d != 'n') {
newAr[i++] = d;
}
return newAr;
}
// imprime el primer valor ingresado
// el penultimo valor es el nuevo inicio
// el primer valor es borrado de la lista
void dequeue() {
Nodo *actual,
*temporal;
contador--;
printf("nEL siguiente cliente a atender es:...n");
clearBuffer();
if (isEmpty()) {
printf("nNO hay clientes Ingrese uno a la cola!n");
} else {
if (final == inicio) { // si solo hay 1 nodo
printf("%d | %sn", final->id, final->nombre);
final = inicio = 0; // dejamos los punteros en null
} else { // si hay mas de 1 nodo
actual = final;
while (actual != inicio) { // recorra la cola y quede en el penultimo
temporal = actual; // temporal guarda la direccion del penultimo
actual = temporal->siguiente;
}
printf("%d | %sn", inicio->id, inicio->nombre); // imprimimos el ultimo nodo
inicio = temporal; // el penultimo es ahora el ultimo
}
}
}
// agrega un nodo nuevo al final de la cola
void enqueue() {
Nodo *nodoNuevo,
*temporal;
nodoNuevo = (Nodo*) malloc(sizeof(Nodo));
clearBuffer();
nodoNuevo->nombre = getPtrNom();
nodoNuevo->id = getId();
contador++;
if (isEmpty()) { // si la cola esta vacia
final = nodoNuevo; // el nodo toma el primer
inicio = nodoNuevo; // y el ultimo lugar
} else { // si hay al menos 1 nodo
temporal = final; // almacenamos el ultimo nodo agregado
final = nodoNuevo; // el nodoNuevo toma el primer lugar
final->siguiente = temporal; // apuntando al nodo que estaba en primer lugar
}
clearBuffer();
}
int isEmpty() {
if (!final) {
return 1;
} else {
return 0;
}
}
// cuando se manejan menus que tienen breaklines, se ocupa limpiar el buffer
// antes de empezar a leer caracteres
void clearBuffer() {
while(getchar() != 'n')
;
}
LISTAS
Definición:
Una lista se comporta como una pila si las inserciones y extracciones las hacemos por un
mismo lado de la lista. También se las llama listas LIFO (Last In First Out - último en entrar
primero en salir)
Importante: Una pila al ser una lista puede almacenar en el campo de información cualquier
tipo de valor (int, char, float, vector de caracteres, un registro, etc.)
Para estudiar el mecanismo de utilización de una pila supondremos que en el campo de
información almacena un entero (para una fácil interpretación y codificación)
Inicialmente la PILA está vacía y decimos que el puntero raiz apunta a NULL (Si apunta a NULL
decimos que no tiene una dirección de memoria, en realidad este valor NULL es el valor cero):
Declaración:
Se declara la estructura tal cual como lo hemos hecho en capítulos anteriores apuntando nodo
a enlace
Y su respectiva declaración de funciones en este caso solo tenemos mostrar_lista e insertar.
Creación:
Insertar :
En esta forma los nodos se organizan de modo que cada uno apunta al siguiente, y el último no
apunta a nada, es decir, el puntero del nodo siguiente vale NULL:
En las listas simples enlazadas existe un nodo especial: el primero. Normalmente diremos que
nuestra lista es un puntero a ese primer nodo y llamaremos a ese nodo cabeza de la lista. Eso
es porque mediante ese único puntero podemos acceder a toda la lista.
Es muy importante que nuestro programa nunca pierda el valor del puntero al primer
elemento, ya que, si no existe ninguna copia de ese valor, y se pierde, será imposible acceder
al nodo y no podremos utilizar la información almacenada ni liberar el espacio de memoria que
ocupa.
Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista está
vacía:
Uso:
Las operaciones sobre listas ordenadas más comunes son:
Alistar datos sin usar arrays
– Insertar: añade un elemento (nodo) a la lista.
– Eliminar: suprime el nodo que contiene un elemento especificado de la lista.
Manipulación a través de funciones:
– ImprimeLista: imprime todos los elementos de la lista.
–ListaVacía: operación booleana que indica si la lista está vacía
Imprimir Lista:
Para imprimir es un proceso muy sencillo solo se coloca un while y que mientas ptr sea
diferente de vacío vaya imprimiendo el dato.
El resto… es solo adorno.
Lista vacía:
Muy sencillo para saber si tu lista esta vacia se puede agregar un contador en la función de
insertar() igualado a 0 y que cuando se seleccione la opción para verificar y está vacía se
coloca un condicional If y si el contador es igual a 0 por la tanto la lista está vacía del resto No.
Ejemplo:
Uniendo todo el código quedaría de esta manera:
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
typedef struct nodo
{
int dato;
struct nodo *enlace;
} LISTA;
void mostrar_lista(LISTA *ptr);
void insertar(LISTA **ptr, int elemento);
int contador=0;
main(){
LISTA *n1 = NULL;
int elemento;
int opcion=0;
printf("Crea tu lista de Numeros Pares:");
do{
printf("nn 1.-Ingresar elemento en la lista.");
printf("nn 2.-Mostrar elementos de la lista.");
printf("nn 0.-Salir del programa.");
printf("nn Opcion: ");
scanf(" %d",&opcion);
switch(opcion) {
case 1:
system("cls");
printf("nIntroduzca elemento: ");
scanf("%d", &elemento);
if(elemento%2==0){
insertar(&n1, elemento);
contador++;
}
break;
case 2:
printf("nLa Lista De Numeros Pares es:n ");
mostrar_lista(n1);
break;
}
} while(opcion!=0);
}
void mostrar_lista(LISTA *ptr){
printf("INICIO:n");
for(int i=0;i<contador;i++){
printf(" ______ ");
}
printf("n");
while(ptr != NULL)
{
printf("|"); printf(" %d| -",ptr->dato);printf("|");printf("---->");
ptr = ptr->enlace;
}
printf("NULL(FIN)");
printf("n");
}
void insertar(LISTA **ptr, int elemento)
{
LISTA *p1, *p2;
p1 = *ptr;
if(p1 == NULL)
{
p1 =(LISTA *) malloc(sizeof(LISTA));
if (p1 != NULL)
{
p1->dato = elemento;
p1->enlace = NULL;
*ptr = p1;
}
}
else
{
while(p1->enlace != NULL)
p1 = p1->enlace;
p2 = (LISTA *)malloc(sizeof(LISTA));
if(p2 != NULL)
{
p2->dato = elemento;
p2->enlace = NULL;
p1->enlace = p2;
}
}
}

Más contenido relacionado

La actualidad más candente

Unidad 3 estructuras lineales estaticas y dinamicas
Unidad 3 estructuras lineales estaticas y dinamicasUnidad 3 estructuras lineales estaticas y dinamicas
Unidad 3 estructuras lineales estaticas y dinamicasrehoscript
 
Diapositiva de l estructura de datos
Diapositiva de l estructura de datosDiapositiva de l estructura de datos
Diapositiva de l estructura de datosmariajuly
 
Pilas y Colas
Pilas y ColasPilas y Colas
Pilas y ColasAlex Pin
 
Funcionamiento de un pila
Funcionamiento de un pilaFuncionamiento de un pila
Funcionamiento de un pilajefer
 
conceptos de Punteros y Nodos
conceptos de Punteros y Nodosconceptos de Punteros y Nodos
conceptos de Punteros y NodosBoris Salleg
 
Arboles y Colas de Prioridad en Java
Arboles y Colas de Prioridad en JavaArboles y Colas de Prioridad en Java
Arboles y Colas de Prioridad en JavaLupitaOMG Garmendia
 
Java pilas (Stacks) y colas (Queues)
Java pilas (Stacks) y colas (Queues)Java pilas (Stacks) y colas (Queues)
Java pilas (Stacks) y colas (Queues)Juan Astudillo
 
Estructura de datos listas, pilas y colas
Estructura de datos listas, pilas y colasEstructura de datos listas, pilas y colas
Estructura de datos listas, pilas y colasElias Peña
 
Estructura de datos. listas, pilas y colas
Estructura de datos. listas, pilas y colasEstructura de datos. listas, pilas y colas
Estructura de datos. listas, pilas y colasIARINAIA
 

La actualidad más candente (19)

Pqueues
PqueuesPqueues
Pqueues
 
Pilas
PilasPilas
Pilas
 
Estructura de Datos (LISTAS, COLAS, PILAS)
Estructura de Datos (LISTAS, COLAS, PILAS)Estructura de Datos (LISTAS, COLAS, PILAS)
Estructura de Datos (LISTAS, COLAS, PILAS)
 
Unidad 3 estructuras lineales estaticas y dinamicas
Unidad 3 estructuras lineales estaticas y dinamicasUnidad 3 estructuras lineales estaticas y dinamicas
Unidad 3 estructuras lineales estaticas y dinamicas
 
Diapositiva de l estructura de datos
Diapositiva de l estructura de datosDiapositiva de l estructura de datos
Diapositiva de l estructura de datos
 
Pilas y Colas
Pilas y ColasPilas y Colas
Pilas y Colas
 
Encapsulamiento
EncapsulamientoEncapsulamiento
Encapsulamiento
 
Funcionamiento de un pila
Funcionamiento de un pilaFuncionamiento de un pila
Funcionamiento de un pila
 
conceptos de Punteros y Nodos
conceptos de Punteros y Nodosconceptos de Punteros y Nodos
conceptos de Punteros y Nodos
 
Listas Pilas Colas
Listas Pilas ColasListas Pilas Colas
Listas Pilas Colas
 
Colas
ColasColas
Colas
 
Arboles y Colas de Prioridad en Java
Arboles y Colas de Prioridad en JavaArboles y Colas de Prioridad en Java
Arboles y Colas de Prioridad en Java
 
Listas Simples Enlazadas
Listas Simples EnlazadasListas Simples Enlazadas
Listas Simples Enlazadas
 
Java pilas (Stacks) y colas (Queues)
Java pilas (Stacks) y colas (Queues)Java pilas (Stacks) y colas (Queues)
Java pilas (Stacks) y colas (Queues)
 
Estructura de datos listas, pilas y colas
Estructura de datos listas, pilas y colasEstructura de datos listas, pilas y colas
Estructura de datos listas, pilas y colas
 
Pilas, colas, y listas estructura de datos
Pilas, colas, y listas estructura de datosPilas, colas, y listas estructura de datos
Pilas, colas, y listas estructura de datos
 
Estructura de datos. listas, pilas y colas
Estructura de datos. listas, pilas y colasEstructura de datos. listas, pilas y colas
Estructura de datos. listas, pilas y colas
 
Listasenlazadas 100517143015-phpapp02
Listasenlazadas 100517143015-phpapp02Listasenlazadas 100517143015-phpapp02
Listasenlazadas 100517143015-phpapp02
 
String
StringString
String
 

Similar a Estructuras dinámicas de Datos en C: Pilas, Colas y Listas

Proyecto estructura
Proyecto estructuraProyecto estructura
Proyecto estructuramercy
 
Estructura de datos
Estructura de datosEstructura de datos
Estructura de datoscharlezgt
 
Sesion n°1 estructura de datos
Sesion n°1 estructura de datosSesion n°1 estructura de datos
Sesion n°1 estructura de datosJosé Braganza
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrbviela6
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrbviela6
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrbviela6
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrbviela6
 
Pilas
PilasPilas
Pilaserik
 
Pilas
PilasPilas
Pilaserik
 
Listas cola y_pila.ranli_y_eladio
Listas cola y_pila.ranli_y_eladioListas cola y_pila.ranli_y_eladio
Listas cola y_pila.ranli_y_eladioRanli Cruz
 
Tad lista, pilas y colas
Tad lista, pilas y colasTad lista, pilas y colas
Tad lista, pilas y colaslabarra90
 
Tad lista, pilas y colas
Tad lista, pilas y colasTad lista, pilas y colas
Tad lista, pilas y colaslabarra90
 
Estructuras dinámicas
Estructuras dinámicasEstructuras dinámicas
Estructuras dinámicasPatriciaU
 
Pilas como estructura de datos..
Pilas como estructura de datos..Pilas como estructura de datos..
Pilas como estructura de datos..NANO-06
 
Examen De Estructura De Datos
Examen De Estructura De DatosExamen De Estructura De Datos
Examen De Estructura De Datosvanessa peñafiel
 

Similar a Estructuras dinámicas de Datos en C: Pilas, Colas y Listas (20)

Proyecto estructura
Proyecto estructuraProyecto estructura
Proyecto estructura
 
Estructura de datos
Estructura de datosEstructura de datos
Estructura de datos
 
Gilmora
GilmoraGilmora
Gilmora
 
Sesion n°1 estructura de datos
Sesion n°1 estructura de datosSesion n°1 estructura de datos
Sesion n°1 estructura de datos
 
Pilas .pptx
Pilas .pptxPilas .pptx
Pilas .pptx
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrb
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrb
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrb
 
Estructura de datos.vrb
Estructura de datos.vrbEstructura de datos.vrb
Estructura de datos.vrb
 
Clase De Colas
Clase De ColasClase De Colas
Clase De Colas
 
Clase De Colas
Clase De ColasClase De Colas
Clase De Colas
 
Pilas
PilasPilas
Pilas
 
Pilas
PilasPilas
Pilas
 
Darwin rodriguez 12-0861_pilasy_colas
Darwin rodriguez 12-0861_pilasy_colasDarwin rodriguez 12-0861_pilasy_colas
Darwin rodriguez 12-0861_pilasy_colas
 
Listas cola y_pila.ranli_y_eladio
Listas cola y_pila.ranli_y_eladioListas cola y_pila.ranli_y_eladio
Listas cola y_pila.ranli_y_eladio
 
Tad lista, pilas y colas
Tad lista, pilas y colasTad lista, pilas y colas
Tad lista, pilas y colas
 
Tad lista, pilas y colas
Tad lista, pilas y colasTad lista, pilas y colas
Tad lista, pilas y colas
 
Estructuras dinámicas
Estructuras dinámicasEstructuras dinámicas
Estructuras dinámicas
 
Pilas como estructura de datos..
Pilas como estructura de datos..Pilas como estructura de datos..
Pilas como estructura de datos..
 
Examen De Estructura De Datos
Examen De Estructura De DatosExamen De Estructura De Datos
Examen De Estructura De Datos
 

Estructuras dinámicas de Datos en C: Pilas, Colas y Listas

  • 1. Estructuras dinámicas de Datos Lenguaje C Realizado por: Carlos Ramses Garcia 01/05/2020
  • 2. CONTENIDO PILAS Definición Creación Declaración Uso Manipulación a través de funciones Ejemplo COLAS Definición Creación Declaración Uso Manipulación a través de funciones Ejemplo LISTAS Definición Creación Declaración Uso Manipulación a través de funciones Ejemplo
  • 3. PILAS Definición: Una pila es una estructura de datos simple. Los datos se van apilando uno tras otro. Podemos abstraer cada elemento como un nodo que puede apuntar a otro nodo. Su modo de acceso es LIFO: el último en entrar es el primero en salir. Las operaciones que tiene son 2: push y pop; la primera le pone un elemento y la segunda quita el último. Declaración: El Nodo: Esto es de lo que estará compuesta nuestra pila, para ello usaremos una lista ligada en donde un nodo apunta a otro y este otro a otro (opcionalmente), así infinitamente. Claro que el elemento siguiente de un nodo es opcional; porque el elemento de hasta abajo no apunta a nadie. También tiene un nombre, que es el dato en sí que guardaremos en la pila. Si quisiéramos que nuestra pila fuera de enteros entonces comenzaríamos cambiando el tipo de dato de char[] a int. El elemento superior: En el inicio de todos los tiempos, debe haber un elemento superior aunque no tenga valor y no apunte a nada. Es decir, aunque la pila esté vacía debemos tener un elemento que será el inicio de todo:
  • 4. Creación: Agregar elementos a la pila: push Veamos la operación push, que agrega un elemento a la pila. El nodo superior es una variable global, por eso no necesitamos recibirla en la función. Lo que hacemos es alojar espacio en memoria para almacenar nuestro nuevo elemento usado memory allocate o malloc, como decidió bautizar esta función el gran Dennis. A ese nuevo nodo le ponemos el dato que llevará (String), y como es el que estará hasta arriba entonces hacemos que apunte hacia el que era el superior; y este nuevo ahora tomará su lugar. Explicado en otras palabras, este nuevo nodo será el superior y apuntará al que antes era el superior; se está poniendo encima de él. La próxima vez que apilemos, se creará otro nuevo y este dejará de ser el superior para pasar a ser el siguiente del nuevo; y así sucesivamente. Eliminar el último elemento (operación pop): Esto es fácil pero interesante a la vez. Como vamos a desapilar el elemento, necesitamos hacer que el elemento superior ahora sea al que apuntaba; es decir, su siguiente. Pero eso no es todo, debemos liberar la memoria que se estaba usando y para ello respaldamos lo que ocupaba el que vamos a eliminar dentro de temporal y llamamos a free. Esto sólo ocurre en caso de que superior no sea nulo.
  • 5. Uso: -Apilar, también conocido como push: agregar un elemento -Desapilar, o la operación pop: quitar el último elemento; es decir, el elemento superior Manipulación a través de funciones: -Imprimir: recorrer la pila e imprimir sus valores. -Tamaño: devolver el tamaño de la pila. -Leer último: leer el elemento superior de la pila. -Vacía: indica si la pila está vacía. Imprimir pila: Imprimir la pila no es una operación necesaria, pero como este es un ejercicio sí lo haremos. Únicamente recorremos toda la pila mientras haya un apuntador a siguiente: Para esto necesitamos un nodo temporal y comenzamos recorriendo desde superior. Asignamos a temporal lo que esté apuntando a siguiente; si ya no apunta a nada entonces temporal será nulo y se terminará el ciclo. Tamaño de pila o stack en C: Esto es muy parecido al de imprimir; pero en lugar de imprimir vamos aumentando un contador dentro del ciclo: Comprobamos si superior es nulo y en caso de que sí ya no hacemos el ciclo, pues la pila está vacía.
  • 6. Operación top o peek de la pila(último elemento): Esto es fácil, se lee el último elemento de la pila y en este caso es un String. Si superior es nulo, se imprime que la pila está vacía. En caso de que no, entonces devolvemos lo que tenga el elemento superior. Método para saber si la pila está vacía: podríamos decir que, si ya tenemos el método tamanio, podríamos regresar un booleano resultante de la comparación de tamanio == 0 pero eso sería un desperdicio de recursos Ya que si la pila tiene 0 elementos todo va bien, pero, ¿qué tal si la pila tiene 100000 elementos? tendríamos que recorrer todos dentro de tamanio para determinar al final que la pila no está vacía. Es por eso que mejor usamos otra lógica… si el elemento superior no apunta a nada, entonces no hay más elementos y por lo tanto la pila está vacía. Ejemplo: Uniendo todo el código quedaría de esta manera: #include <stdio.h> // printf #include <stdlib.h> // malloc y free #include <stdbool.h> // Booleanos // Un nodo tiene un dato, el cual es el Nombre. Y otro nodo al que apunta struct nodo { char Nombre[45]; struct nodo *siguiente; }; // Prototipos de funciones
  • 7. void agregar(); // push void eliminarUltimo(void); // pop void imprimir(void);// Mostrar int tamanio(void); // El tamaño de la pila bool vacia(void); // Indica si la pila está vacía void ultimo(void); // El último elemento. // Todo comienza con el nodo superior struct nodo *superior = NULL; int main() { int eleccion; int Nombre1[45]; while (eleccion != 7) { printf("nn--BIENVENIDO A LA PILA DEL ALMACEN--n1.- Agregar Objeton2.- Quitar Objeton3.- Mostrar " "pilan4.- Mostrar Cantidad de Objetos n5.- Comprobar si esta vacian6.- " "Mostrar ultimo Objeton-7.- SalirnntElige: "); scanf("%d", &eleccion); switch (eleccion) { case 1: agregar(); break; case 2: eliminarUltimo(); break; case 3: imprimir(); break; case 4: printf("La pila tiene %d Objetosn", tamanio());
  • 8. break; case 5: if (vacia()) { printf("La pila esta vacian"); } else { printf("La pila NO esta vacian"); } break; case 6: ultimo(); break; } } } int tamanio(void) { int contador = 0; if (superior == NULL) return contador; struct nodo *temporal = superior; while (temporal != NULL) { contador++; temporal = temporal->siguiente; } return contador; } bool vacia(void) { return superior == NULL; }
  • 9. void ultimo() { if (superior != NULL){ printf("El Ultimo Objeto es: %sn", superior->Nombre); } else { printf("La pila esta Vacia!!"); } } // Operación push void agregar() { // El que se agregará; reservamos memoria nodo *nuevoNodo; nuevoNodo =(struct nodo *) malloc(sizeof(struct nodo)); // Le ponemos el dato printf("Ingresa el nombre del objeto:n"); scanf("%s",&nuevoNodo->Nombre); printf("Agregando %s...n", nuevoNodo->Nombre); // Y ahora el nuevo nodo es el superior, y su siguiente // es el que antes era superior nuevoNodo->siguiente = superior; superior = nuevoNodo; } void imprimir(void) {
  • 10. printf("Imprimiendo...n"); struct nodo *temporal = superior; if(temporal == NULL){ printf("No hay objetos en la pila!!n"); } while (temporal != NULL) { printf("%sn", temporal->Nombre); temporal = temporal->siguiente; } } // Operación pop, eliminar el de hasta arriba void eliminarUltimo(void) { printf("Los trabajadores estan Quitando el Ultimo Objeto...n"); if (superior != NULL) { // Para liberar la memoria más tarde debemos // tener la referencia al que vamos a eliminar struct nodo *temporal = superior; // Ahora superior es a lo que apuntaba su siguiente superior = superior->siguiente; // Liberar memoria que estaba ocupando el que eliminamos free(temporal); } }
  • 11. COLAS Definición: Una cola es un tipo especial de lista enalazada en la que sólo se pueden insertar nodos en uno de los extremos de la lista y sólo se pueden eliminar nodos en el otro. Además, como sucede con las pilas, las escrituras de datos siempre son inserciones de nodos, y las lecturas siempre eliminan el nodo leído. Este tipo de lista es conocido como lista FIFO (First In First Out), el primero en entrar es el primero en salir. Declaración: El símil cotidiano es una cola para comprar, por ejemplo, las entradas del cine. Los nuevos compradores sólo pueden colocarse al final de la cola, y sólo el primero de la cola puede comprar la entrada. El nodo típico para construir pilas es el mismo que vimos en los capítulos anteriores para la construcción de pilas: Los tipos que definiremos normalmente para manejar colas serán casi los mismos que para manejar listas y pilas, tan sólo cambiaremos algunos nombres: Nodo es el tipo para declarar nodos, evidentemente. Es evidente, que una cola es una lista abierta. Así que sigue siendo muy importante que nuestro programa nunca pierda el valor del puntero al primer elemento, igual que pasa con las listas abiertas. Además, debido al funcionamiento de las colas, también deberemos mantener un puntero para el último elemento de la cola, que será el punto donde insertemos nuevos nodos. Teniendo en cuenta que las lecturas y escrituras en una cola se hacen siempre en extremos distintos, lo más fácil será insertar nodos por el final, a continuación del nodo que no tiene nodo siguiente, y leerlos desde el principio, hay que recordar que leer un nodo implica eliminarlo de la cola.
  • 12. Creación: Agregar Elementos A la Cola(Operación Enqueue): Se llaman los datos extraidos a la función que creamos para crear la cola: Lo que hacemos es alojar espacio en memoria para almacenar nuestro nuevo elemento usado memory allocate o malloc, como decidió bautizar esta función el gran Dennis. A ese nuevo nodo le ponemos el dato que llevará (el entero), y como es el que estará hasta arriba entonces hacemos que apunte hacia el que era el superior; y este nuevo ahora tomará su lugar, (Justo como en la pila). Se limpia el buffer le almacenan los datos obtenidos en nodoNuevo->nombre y en nodoNuevo->id para poderlos trabajar Entonces si la cola está vacía el nodo toma el primer y último lugar si no entonces el ultimo nodo se agrega el nodoNuevo toma el primer lugar para que después quede final apuntando siguiente igualando a temporal.
  • 13. Eliminar el Primer elemento (operación Dequeue): Recordemos que leer un elemento de una cola, implica eliminarlo. Ahora también existen dos casos, que la cola tenga un solo elemento o que tenga más de uno. Usaremos un puntero a un nodo auxiliar: Hacemos que nodo apunte al primer elemento de la cola, es decir a primero. Asignamos a primero la dirección del segundo nodo de la pila: primero->siguiente. Guardamos el contenido del nodo para devolverlo como retorno, recuerda que la operación de lectura en colas implica también borrar. Liberamos la memoria asignada al primer nodo, el que queremos eliminar. Leer un elemento en una cola con un solo elemento: También necesitamos un puntero a un nodo auxiliar: Hacemos que nodo apunte al primer elemento de la pila, es decir a primero. Asignamos NULL a primero, que es la dirección del segundo nodo teórico de la cola: primero->siguiente. Guardamos el contenido del nodo para devolverlo como retorno, recuerda que la operación de lectura en colas implica también borrar. Liberamos la memoria asignada al primer nodo, el que queremos eliminar. Hacemos que último apunte a NULL, ya que la lectura ha dejado la cola vacía.
  • 14. Leer un elemento en una cola, Caso general: Hacemos que nodo apunte al primer elemento de la pila, es decir a primero. Asignamos a primero la dirección del segundo nodo de la pila: primero->siguiente. Guardamos el contenido del nodo para devolverlo como retorno, recuerda que la operación de lectura en colas implica también borrar. Liberamos la memoria asignada al primer nodo, el que queremos eliminar. Si primero es NULL, hacemos que ultimo también apunte a NULL, ya que la lectura ha dejado la cola vacía. Uso: De nuevo nos encontramos ante una estructura con muy pocas operaciones disponibles. Las colas sólo permiten añadir y leer elementos: Añadir: Inserta un elemento al final de la cola. Leer: Lee y elimina un elemento del principio de la cola. Manipulación a través de funciones: Con estas funciones getId() Y getpTrnom() lo que hicimos fue extraer cada dato por separado y devolverlos para poder trabajarlos en la función enqueue(); Con la función isEmptywrap llamamos un valor que nos genera isEmpty() donde se verifica si final está totalmente vacía retorna 1 por lo tanto imprimirá “la cola esta vacia!” si no el caso contrario
  • 15. Función donde se verifica si final esta vacío Ejemplo: Uniendo todo el código quedaría de esta manera: #include <stdio.h> #include <stdlib.h> // Un nodo tiene un dato, el cual es el Nombre y el id. Y otro nodo al que apunta struct persona { int id; char *nombre; struct persona *siguiente; }; int contador=0; //Prototipos de funciones char* getPtrNom(); int getId(); int isEmpty(); int menu(); void clearBuffer(); void dequeue(); void enqueue(); void isEmptyWrap();
  • 16. typedef struct persona Nodo; Nodo *final; Nodo *inicio; main() { final = inicio = 0; return menu(); } int menu() { char c; printf("nn--Servitec c.a--n"); printf("nn-Cola para atender a los clientes-n"); do { printf("n~~ MENU: cola! ~~"); printf("nHaga una seleccion:"); printf("n 1.-Ingresar a la cola (enqueue)"); printf("n 2.-Atender Cliente(dequeue)"); printf("n 3.-Cuantas personas hay en la cola?"); printf("n 4.-Comprobar si esta vacia(isEmpty)"); printf("n q: salir.n"); c = getchar(); switch(c) { case '1': enqueue();
  • 17. break; case '2': dequeue(); break; case '3': printf(" Numero de Clientes en la cola: %d !n",contador); break; case '4': isEmptyWrap(); break; // default : // printf(" Seleccione una de las opciones establecidas!"); // break; } } while(c != 'q' && c != EOF); return 1; } // metodo wrapper para el menu void isEmptyWrap() { clearBuffer(); if (isEmpty()) { printf("La Cola Esta Vacia!n"); } else { printf("La Cola NO Esta Vacia!n"); } } int getId() { int num;
  • 18. printf("Ingrese el ID: "); scanf("%d" , &num); return num; } // retorna un nuevo puntero a un arreglo char* getPtrNom() { char d,*newAr; int i = 0; newAr = (char*) malloc(sizeof(char)*100); printf("Ingrese el nombre: "); while((d = getchar()) != EOF && d != 'n') { newAr[i++] = d; } return newAr; } // imprime el primer valor ingresado // el penultimo valor es el nuevo inicio // el primer valor es borrado de la lista void dequeue() { Nodo *actual, *temporal; contador--; printf("nEL siguiente cliente a atender es:...n"); clearBuffer();
  • 19. if (isEmpty()) { printf("nNO hay clientes Ingrese uno a la cola!n"); } else { if (final == inicio) { // si solo hay 1 nodo printf("%d | %sn", final->id, final->nombre); final = inicio = 0; // dejamos los punteros en null } else { // si hay mas de 1 nodo actual = final; while (actual != inicio) { // recorra la cola y quede en el penultimo temporal = actual; // temporal guarda la direccion del penultimo actual = temporal->siguiente; } printf("%d | %sn", inicio->id, inicio->nombre); // imprimimos el ultimo nodo inicio = temporal; // el penultimo es ahora el ultimo } } } // agrega un nodo nuevo al final de la cola void enqueue() { Nodo *nodoNuevo, *temporal; nodoNuevo = (Nodo*) malloc(sizeof(Nodo)); clearBuffer();
  • 20. nodoNuevo->nombre = getPtrNom(); nodoNuevo->id = getId(); contador++; if (isEmpty()) { // si la cola esta vacia final = nodoNuevo; // el nodo toma el primer inicio = nodoNuevo; // y el ultimo lugar } else { // si hay al menos 1 nodo temporal = final; // almacenamos el ultimo nodo agregado final = nodoNuevo; // el nodoNuevo toma el primer lugar final->siguiente = temporal; // apuntando al nodo que estaba en primer lugar } clearBuffer(); } int isEmpty() { if (!final) { return 1; } else { return 0; } } // cuando se manejan menus que tienen breaklines, se ocupa limpiar el buffer // antes de empezar a leer caracteres void clearBuffer() { while(getchar() != 'n') ; }
  • 21. LISTAS Definición: Una lista se comporta como una pila si las inserciones y extracciones las hacemos por un mismo lado de la lista. También se las llama listas LIFO (Last In First Out - último en entrar primero en salir) Importante: Una pila al ser una lista puede almacenar en el campo de información cualquier tipo de valor (int, char, float, vector de caracteres, un registro, etc.) Para estudiar el mecanismo de utilización de una pila supondremos que en el campo de información almacena un entero (para una fácil interpretación y codificación) Inicialmente la PILA está vacía y decimos que el puntero raiz apunta a NULL (Si apunta a NULL decimos que no tiene una dirección de memoria, en realidad este valor NULL es el valor cero): Declaración: Se declara la estructura tal cual como lo hemos hecho en capítulos anteriores apuntando nodo a enlace Y su respectiva declaración de funciones en este caso solo tenemos mostrar_lista e insertar. Creación: Insertar :
  • 22. En esta forma los nodos se organizan de modo que cada uno apunta al siguiente, y el último no apunta a nada, es decir, el puntero del nodo siguiente vale NULL: En las listas simples enlazadas existe un nodo especial: el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo y llamaremos a ese nodo cabeza de la lista. Eso es porque mediante ese único puntero podemos acceder a toda la lista. Es muy importante que nuestro programa nunca pierda el valor del puntero al primer elemento, ya que, si no existe ninguna copia de ese valor, y se pierde, será imposible acceder al nodo y no podremos utilizar la información almacenada ni liberar el espacio de memoria que ocupa. Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista está vacía: Uso: Las operaciones sobre listas ordenadas más comunes son: Alistar datos sin usar arrays – Insertar: añade un elemento (nodo) a la lista. – Eliminar: suprime el nodo que contiene un elemento especificado de la lista. Manipulación a través de funciones: – ImprimeLista: imprime todos los elementos de la lista. –ListaVacía: operación booleana que indica si la lista está vacía Imprimir Lista: Para imprimir es un proceso muy sencillo solo se coloca un while y que mientas ptr sea diferente de vacío vaya imprimiendo el dato. El resto… es solo adorno.
  • 23. Lista vacía: Muy sencillo para saber si tu lista esta vacia se puede agregar un contador en la función de insertar() igualado a 0 y que cuando se seleccione la opción para verificar y está vacía se coloca un condicional If y si el contador es igual a 0 por la tanto la lista está vacía del resto No. Ejemplo: Uniendo todo el código quedaría de esta manera: #include <stdio.h> #include <stdlib.h> #include<conio.h> typedef struct nodo { int dato; struct nodo *enlace; } LISTA; void mostrar_lista(LISTA *ptr); void insertar(LISTA **ptr, int elemento); int contador=0; main(){ LISTA *n1 = NULL; int elemento; int opcion=0; printf("Crea tu lista de Numeros Pares:"); do{ printf("nn 1.-Ingresar elemento en la lista."); printf("nn 2.-Mostrar elementos de la lista."); printf("nn 0.-Salir del programa.");
  • 24. printf("nn Opcion: "); scanf(" %d",&opcion); switch(opcion) { case 1: system("cls"); printf("nIntroduzca elemento: "); scanf("%d", &elemento); if(elemento%2==0){ insertar(&n1, elemento); contador++; } break; case 2: printf("nLa Lista De Numeros Pares es:n "); mostrar_lista(n1); break; } } while(opcion!=0);
  • 25. } void mostrar_lista(LISTA *ptr){ printf("INICIO:n"); for(int i=0;i<contador;i++){ printf(" ______ "); } printf("n"); while(ptr != NULL) { printf("|"); printf(" %d| -",ptr->dato);printf("|");printf("---->"); ptr = ptr->enlace; } printf("NULL(FIN)"); printf("n"); } void insertar(LISTA **ptr, int elemento) { LISTA *p1, *p2; p1 = *ptr;
  • 26. if(p1 == NULL) { p1 =(LISTA *) malloc(sizeof(LISTA)); if (p1 != NULL) { p1->dato = elemento; p1->enlace = NULL; *ptr = p1; } } else { while(p1->enlace != NULL) p1 = p1->enlace; p2 = (LISTA *)malloc(sizeof(LISTA)); if(p2 != NULL) { p2->dato = elemento; p2->enlace = NULL; p1->enlace = p2; } } }