Está en la página 1de 16

Tema 12: ESTRUCTURAS DINMICAS

TEMA 12: ESTRUCTURAS DINMICAS. GESTIN DINMICA DE MEMORIA

1.- FUNCIONES DE ASIGNACIN DINMICA


Una vez compilados todos los programas de C organizan la memoria de la computadora en 4 regiones.

cdigo

64 Kb

datos globales pila montn o heap 64 Kb

En la PILA son colocados los datos automticos que se crean y se liberan a medida que se ejecuta el programa. Por ejemplo, la pila crece con cada entrada en una funcin para crear espacio para todas las variables locales necesarias durante la duracin de la funcin, decrece a cada salida. El MONTN o heap es el rea de memoria libre que es gestionada por las funciones de asignacin dinmica malloc() y free(). - La funcin malloc() asigna memoria en tiempo de ejecucin y devuelve un puntero void al comienzo de esa memoria. - La funcin free() devuelve al montn memoria previamente asignada para que pueda ser reutilizada. Los prototipos de estas funciones son: void *malloc (unsigned int); void free (void *p); Ambas funciones usan el archivo de cabecera <stdlib.h> <alloc.h>. El nico argumento de malloc es de tipo unsigned int, lo que significa que esta funcin permite reservar espacios cuya longitud no sobrepase los 64 K. Si no hay suficiente memoria libre para satisfacer la peticin malloc(), devuelve un nulo. Como el resultado devuelto por malloc es un puntero genrico (void), podr por tanto ser convertido implcitamente (sin casting, sin obligarle a) en un puntero de cualquier tipo, sin embargo, es conveniente utilizar la conversin para saber el tipo de puntero con el que estamos trabajando. Es importante llamar a free() slo con un puntero vlido previamente asignado. De otro modo puede producir un fallo en el programa. Ej.- char *p; p=malloc(25); <=> p=(char*)malloc(25); casting a puntero char Despus de la asignacin, p apunta al primero de los 25 bytes libres de memoria.

E. dinmicas 1

Tema 12: ESTRUCTURAS DINMICAS

Ej.- int *ptr; ptr=(int*) malloc (50 *sizeof(int)); Dispone espacio para 50 enteros, el uso de sizeof es para asegurar la portabilidad. Como el montn no es infinito, siempre que se asigne memoria, es necesario comprobar antes de usar el puntero el valor devuelto por malloc(), para asegurar que no es nulo.

Ej.- char *p; p=malloc(25); if (p==NULL) { printf(\n No hay memoria suficiente); exit(1); }

2.- ESTRUCTURAS DINMICAS


Las estructuras estticas, necesitan un espacio de asignacin de memoria fijo. Sin embargo, en la prctica suelen darse casos en los que una estructura de datos pueda aumentar o disminuir sin que el programador conozca previamente el tamao de sta. Por ello es necesario un mecanismo que no realice una asignacin fija de memoria, sino que sea variable con el tiempo, es decir, que sea dinmica. El mecanismo principal de esta asignacin dinmica de memoria para almacenar ciertos elementos de una estructura es el puntero. Luego las estructuras dinmicas no existen por s mismas, sino que se basan en una implementacin con variables puntero. Entre las estructuras dinmicas tenemos: Las Listas Enlazadas Pilas Colas rboles Binarios Todas estas estructuras estn basadas en la utilizacin de nodos de datos. Un nodo en su forma ms bsica consta de dos partes: - rea de datos o informacin (a) - Puntero al siguiente nodo (b)

(a)

(b)

2.1.- LISTAS ENLAZADAS


Una lista es un conjunto de nodos relacionados entre s. Cada nodo consta de dos partes: una donde se almacena la informacin y otra donde se guarda una referencia al siguiente nodo, es decir, un puntero a otro nodo, de este modo, cada nodo apunta al siguiente. Los nodos pueden estar situados en posiciones diferentes de la memoria que no tienen porque ser contiguas ( en los vectores cada elemento ocupa una posicin de memoria consecutiva), por ello es necesario el campo enlace, que contiene el puntero que apunta al siguiente nodo al que se encuentra conectado. El puntero del ltimo elemento de la lista debe tener el valor nulo (NULL). Su representacin grfica sera:

E. dinmicas 2

Tema 12: ESTRUCTURAS DINMICAS

Para poder realizar la implementacin del tipo lista enlazada en C es necesaria la utilizacin de estructuras autorreferenciadas, es decir, estructuras en las que uno de sus miembros es un puntero que referencia a la misma estructura. La componente de una lista quedara: Ej.- struct nodo { struct nombre estructura informacin; struct nodo *enlace }; Ej.- struct componente { tipo_elemento elemento; struct componente*enlace; }; La lista completa sera un puntero a una estructura de este tipo: typedef struct componente *tipo_lista mientras que la lista vaca es un puntero a NULL. tipo lista listavacia; listavacia= NULL;

2.1.1.- OPERACIONES BSICAS CON UNA LISTA


Vamos a ver mediante un programa cmo se crea una lista enlazada, para ello lo primero que tenemos que hacer es definir sus nodos o elementos, teniendo en cuenta que cada nodo consta de un campo informacin que a su vez puede ser una estructura y un campo enlace que autorreferenciar al propio nodo. typedef struct nodo{ int dato; struct nodo *enlace; }LISTA; Para referenciar la lista completa necesitamos un puntero a la estructura LISTA. que llamaremos n1 y que inicializaremos a NULL para crear una lista vaca. Vamos a llenar la lista con nmeros enteros hasta que introduzcamos un 0, y vamos a enlazar los elementos en el orden que entran, para ello utilizaremos una funcin insertar, como a dicha funcin la vamos a pasar una estructura, deberemos pasar como parmetro la direccin de la estructura (que a su vez es un puntero a dicha estructura) es decir, un puntero que apunta a la direccin de memoria donde se encuentra la estructura. se invoca con la direccin y se recibe con puntero Una vez llena la lista la visualizaremos invocando a la funcin mostrar. Ejemplo1: CREACIN DE UNA LISTA ENLAZADA

E. dinmicas 3

Tema 12: ESTRUCTURAS DINMICAS

#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); main() { LISTA *n1 = NULL; int elemento; clrscr(); do { printf("\nIntroduzca un nmero entero o 0 para fin: "); scanf("%d",&elemento); if(elemento != 0) insertar(&n1, elemento); } while(elemento != 0); printf("\nLa nueva lista enlazada es: "); mostrar_lista(n1); } void mostrar_lista(LISTA *ptr) { while(ptr != NULL) { printf("%d",ptr->dato); ptr = ptr->enlace; } printf("\n"); } void insertar(LISTA **ptr, int elemento) { LISTA *p1, *p2; p1 = *ptr; if(p1 == NULL) /* la lista est vaca */ {

E. dinmicas 4

Tema 12: ESTRUCTURAS DINMICAS

p1 = malloc(sizeof(LISTA)); if (p1 != NULL) { p1->dato = elemento; p1->enlace = NULL; *ptr = p1; } } else /* la lista contiene algn elemento */ { while(p1->enlace != NULL) p1 = p1->enlace; /* recorro hasta llegar al final donde inserto */ p2 = malloc(sizeof(LISTA)); if(p2 != NULL) { p2->dato = elemento; p2->enlace = NULL; p1->enlace = p2; } } }

salida: Introduzca un nmero entero o 0 para fin: 3 Introduzca un nmero entero o 0 para fin: 7 Introduzca un nmero entero o 0 para fin: 8 Introduzca un nmero entero o 0 para fin: 9 Introduzca un nmero entero o 0 para fin: 0 La nueva lista enlazada es: 3789

Ejemplo2: crear una lista con tres caracteres por asignacin e insertar un carcter al principio y otro al final.

#include <stdio.h> #include <stdlib.h> #include <conio.h> typedef struct nodo {

E. dinmicas 5

Tema 12: ESTRUCTURAS DINMICAS

char dato; struct nodo *enlace; } LISTA; void mostrar_lista(LISTA *ptr); void insertar_al_principio(LISTA **ptr, char item); void insertar_al_final(LISTA *ptr, char item); main() { LISTA *n1, *n2, *n3; clrscr(); n1 = malloc(sizeof(LISTA)); n2 = malloc(sizeof(LISTA)); n3 = malloc(sizeof(LISTA)); printf(\n LISTA ocupa %d octetos ,sizeof(LISTA)); printf("\n &n1 = %u",&n1); printf("\n &n2 = %u",&n2); printf("\n &n3 = %u",&n3); printf("\n n1 = %u",n1); printf("\n n2 = %u",n2); printf("\n n3 = %u",n3); n1->dato = 'c'; n1->enlace = n2; n2->dato = 'a'; n2->enlace = n3; n3->dato = 't'; n3->enlace = NULL; printf("\n La lista enlazada es como sigue: "); mostrar_lista(n1); insertar_al_principio(&n1,'s'); printf("\n n1 = %u",n1); printf("\n La nueva lista enlazada es: "); mostrar_lista(n1); insertar_al_final(n1,'m'); printf("\n La nueva lista enlazada es: "); mostrar_lista(n1); }

void mostrar_lista(LISTA *ptr) { while(ptr != NULL) { printf("%c",ptr->dato); ptr = ptr->enlace; }

E. dinmicas 6

Tema 12: ESTRUCTURAS DINMICAS

printf("\n"); } void insertar_al_principio(LISTA **ptr, char item) { LISTA *new; new = malloc(sizeof(LISTA)); printf("\n &new = %u",&new); printf("\n new =%u",new); if(new != NULL) { new->dato = item; new->enlace = *ptr; *ptr = new; } } void insertar_al_final(LISTA *ptr, char item) { LISTA *new; while(ptr->enlace != NULL) ptr = ptr->enlace; new = malloc(sizeof(LISTA)); printf("\n new =%u",new); if(new != NULL) { ptr->enlace = new; new->dato = item; new->enlace = NULL; } }

salida: LISTA ocupa 5 octetos &n1 = 6553088 &n2 = 6553084 &n3 = 6553080 n1 = 6693540 n2 = 6693556 n3 = 6693572 La lista enlazada es como sigue: cat &new = 6553056 new =6693588 n1 = 6693588 La nueva lista enlazada es: scat new =6693604 La nueva lista enlazada es: scatm

E. dinmicas 7

Tema 12: ESTRUCTURAS DINMICAS

Ejercicio1: Bsqueda de un elemento en una lista enlazada, introduciendo el elemento a buscar por teclado.

#include <stdio.h> #include <stdlib.h> typedef struct nodo { char dato; struct nodo *enlace; } LISTA; void mostrar_lista(LISTA *ptr); int buscar_en_lista(LISTA *ptr, char item); main() { LISTA *n1, *n2, *n3, *n4; char item; int encontrado; n1 = malloc(sizeof(LISTA)); n2 = malloc(sizeof(LISTA)); n3 = malloc(sizeof(LISTA)); n4 = malloc(sizeof(LISTA)); n1->dato = 'a'; n1->enlace = n2; n2->dato = 'b'; n2->enlace = n3; n3->dato = 'c'; n3->enlace = n4; n4->dato = 'd'; n4->enlace = NULL; printf("La lista enlazada es como sigue: "); mostrar_lista(n1); printf("Introduzca un caracter a buscar en la lista: "); item = getchar(); encontrado = buscar_en_lista(n1,item); printf("\nEl caracter %c ",item); if (encontrado) printf("sido encontrado en la lista: "); else printf("no ha sido encontrado en la lista: "); mostrar_lista(n1); } void mostrar_lista(LISTA *ptr) {

E. dinmicas 8

Tema 12: ESTRUCTURAS DINMICAS

while(ptr != NULL) { printf("%c",ptr->dato); ptr = ptr->enlace; } printf("\n"); } int buscar_en_lista(LISTA *ptr, char item) { if(ptr == NULL) return(0); else { do { if(ptr->dato == item) return(1); ptr = ptr->enlace; } while(ptr != NULL); return(0); } }

EJERCICIO 2: Llenar una lista enlazada con nmeros enteros (ordenados de menor a mayor) hasta introducir un cero e inserte un numero entero en la posicin correcta de la lista enlazada.

#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); void insertar_ordenado(LISTA **ptr,int item); main() { LISTA *n1 = NULL;

E. dinmicas 9

Tema 12: ESTRUCTURAS DINMICAS

int elemento; clrscr(); do { printf("\nIntroduzca un nmero entero o 0 para fin: "); scanf("%d",&elemento); if(elemento != 0) insertar(&n1, elemento); } while(elemento != 0); printf("\nLa nueva lista enlazada es: "); mostrar_lista(n1); printf("\n introduce elemento a insertar:"); scanf("%d",&elemento); insertar_ordenado(&n1,elemento); printf("\n lanueva lista despues de insertar es:"); mostrar_lista(n1); getchar(); getchar(); } void mostrar_lista(LISTA *ptr) { while(ptr != NULL) { printf("%d",ptr->dato); ptr = ptr->enlace; } printf("\n"); } void insertar(LISTA **ptr, int elemento) { LISTA *p1, *p2; p1 = *ptr; if(p1 == NULL) { p1 = malloc(sizeof(LISTA)); if (p1 != NULL) { p1->dato = elemento; p1->enlace = NULL; *ptr = p1; } } else {

E. dinmicas 10

Tema 12: ESTRUCTURAS DINMICAS

while(p1->enlace != NULL) p1 = p1->enlace; p2 = malloc(sizeof(LISTA)); if(p2 != NULL) { p2->dato = elemento; p2->enlace = NULL; p1->enlace = p2; } } } void insertar_ordenado(LISTA**ptr,int item) { LISTA *nuevo,*aux,*precede; int encontrado=0; aux=*ptr; while(!encontrado && aux!=NULL) { if (item < aux->dato ) encontrado=1; else { precede=aux; aux=aux->enlace; } } nuevo = malloc(sizeof(LISTA)); if (nuevo != NULL) nuevo->dato=item; if (*ptr==aux) /*dato se inserta al principio */ { nuevo->enlace=*ptr; *ptr=nuevo; } else { precede->enlace=nuevo; nuevo->enlace=aux; } }

salida: Introduzca un nmero entero o 0 para fin: 2 Introduzca un nmero entero o 0 para fin: 4 Introduzca un nmero entero o 0 para fin: 7

E. dinmicas 11

Tema 12: ESTRUCTURAS DINMICAS

Introduzca un nmero entero o 0 para fin: 9 Introduzca un nmero entero o 0 para fin: 0 La nueva lista enlazada es: 2479 introduce elemento a insertar:5 la nueva lista despues de insertar es:24579

2.2.- PILAS
Una pila se define como una lista enlazada de elementos en la cual un elemento slo puede ser aadido o eliminado por un extremo llamado CIMA. Las pilas se conocen como estructuras LIFO (Last In First Out, ltimo en entrar, primero en salir). Como una pila es una estructura dinmica de datos, vara conforme se quiten o aadan elementos. Es necesario definir dos operaciones relacionadas con la insercin de elementos: Introducir o meter datos en la pila (push) que es la operacin que aade un elemento por la cima de la pila, modificando a la vez la direccin de sta (cima). Extraer o sacar datos de la pila (pop) que es la operacin que elimina el elemento de la cima generando un nuevo valor de sta. Antes de meter algn elemento, hay que generar dicha pila, es decir, necesitamos otra operacin que cree la pila vaca. Antes de sacar un elemento se debe comprobar si la pila est vaca o no.

PILA

Cima a

PILA NULL

PILA

Cima c

NULL

/* Implementacin de una pila de caracteres */ #include <stdio.h> #include <conio.h> #include <stdlib.h> typedef struct nodo{ char dato; struct nodo *enlace; }PILA; void mostrar(PILA *ptr);

E. dinmicas 12

Tema 12: ESTRUCTURAS DINMICAS

int vacia(PILA *ptr); void introducir(PILA ** ptr, char item); char extraer(PILA**ptr); main () { PILA *pila=NULL; clrscr(); introducir(&pila,'a'); introducir(&pila,'b'); introducir(&pila,'c'); printf("La pila es como sigue:"); mostrar(pila); printf ("\nEl primer elemento obtenido es %c\n",extraer(&pila)); printf ("\nEl segundo elemento obtenido es %c\n",extraer(&pila)); printf ("\nEl tercer elemento obtenido es %c\n",extraer(&pila)); extraer(&pila); getche(); } void mostrar(PILA *ptr) { while(ptr!=NULL) { printf("%c",ptr->dato); ptr=ptr->enlace; } printf("\n"); } int vacia(PILA *ptr) { if (ptr==NULL) return(1); else return(0); } void introducir(PILA **ptr,char item) { PILA *p; if (vacia(*ptr)) { p=(PILA *)malloc(sizeof(PILA)); if(p!=NULL) { p->dato=item; p->enlace=NULL; *ptr=p; } }

E. dinmicas 13

Tema 12: ESTRUCTURAS DINMICAS

else { p=(PILA *)malloc(sizeof(PILA)); if(p!=NULL) { p->dato=item; p->enlace=*ptr; *ptr=p; } } } char extraer(PILA**ptr) { PILA *p1; p1=*ptr; char item; if(vacia(p1)) { printf("Error! La pila esta vacia\n"); } else { item=p1->dato; *ptr=p1->enlace; free(p1); return(item); } }

2.3.- COLAS Una cola se define como una lista enlazada de elementos en la que las eliminaciones se producen por un extremo llamado FRENTE o CABEZA y las inserciones por el otro extremo llamado FINAL O COLA Se la denomina tambin estructura FIFO (First In First Out, primero en entrar, primero en salir). Una cola puede tambin implementarse como una lista doblemente enlazada. Se utilizan dos punteros para acceder a la cola. En este caso, los nodos que constituyen la lista enlazada de la cola contienen dos campos de enlace. Un campo de enlace se utiliza para apuntar al siguiente nodo de la lista y el otro para apuntar al nodo anterior de la lista. La estructura en C sera: typedef struct nodo { char dato; struct nodo*enlace_sig; struct nodo*enlace_ant; }COLA;

cabeza

E. dinmicas 14

Tema 12: ESTRUCTURAS DINMICAS

NULL

c NULL

/* Implementar una COLA introduciendo y eliminando datos, al eliminar liberar memoria */ #include <conio.h> #include <stdio.h> #include <stdlib.h> typedef struct nodo { char dato; struct nodo *enlace; }COLA; void mostrar_cola(COLA*ptr); int vacia(COLA*ptr); void encolar(COLA**cabeza,char item); char desencolar(COLA**cabeza); main() { COLA *cabeza=NULL; encolar (&cabeza,'a'); encolar (&cabeza,'b'); encolar (&cabeza,'c'); printf("La cola es: "); mostrar_cola(cabeza); printf("\n El primer elemento de la cola es %c\n",desencolar(&cabeza)); printf("\n El segundo elemento de la cola es %c\n",desencolar(&cabeza)); printf("\n El tercero elemento de la cola es %c\n",desencolar(&cabeza)); desencolar(&cabeza); getche(); } void mostrar_cola(COLA*ptr) { while(ptr!=NULL) { printf("%c",ptr->dato); ptr=ptr->enlace; } printf("\n"); } int vacia(COLA *ptr)

E. dinmicas 15

Tema 12: ESTRUCTURAS DINMICAS

{ if (ptr==NULL) return(1); else return(0); } void encolar(COLA**cabeza,char item) { COLA *p; p=(COLA*)malloc(sizeof(COLA)); if (p!=NULL) { p->dato=item; p->enlace=*cabeza; *cabeza=p; } } char desencolar(COLA**cabeza) { COLA *p1,*p2; p1=*cabeza; char item; if(vacia(p1)) { printf("Error! La cola esta vacia\n"); } else { p2=*cabeza; while(p2->enlace!=NULL) { p1=p2; p2=p2->enlace; } item=p2->dato; p1->enlace=NULL; free(p2); if(p1==p2) *cabeza=NULL; return (item); } }

E. dinmicas 16

También podría gustarte