Vous êtes sur la page 1sur 25

Tema 6

Estructuras dinámicas

Administración de Sistemas Informáticos 17/10/08 13:16


1. Introducción
 Un programa guarda información en la
memoria de dos formas:
– Variables locales y globales
 variables globales y estáticas (static)
– Almacenamiento en la zona de datos del programa.
 variables locales
– Almacenamiento en la pila.
 Estas variables requieren que el programador
conozca, de antemano, la cantidad de espacio
necesario para cada una de ellas.
Administración de Sistemas Informáticos 17/10/08 13:16
1. Introducción
– Sistema de asignación dinámica.
 Se asigna tanto espacio de memoria libre para el almacenamiento
de la información como sea necesario y se vuelve a convertir en
memoria libre cuando ya se ha utilizado.
 La memoria libre se encuentra entre el área de almacenamiento
permanente del programa (segmento de datos) y la pila.
 Esta región se denomina zona de memoria dinámica o heap
(montón).
 Se puede reutilizar.
 Permite la creación de estructuras complejas como listas enlazadas
y árboles binarios.
 Para realizar asignación dinámica de memoria, se usan los punteros.
 El uso de punteros permite escribir programas grandes y más
flexibles, y especialmente útil cuando se escriben programas
orientados a objetos.

Administración de Sistemas Informáticos 17/10/08 13:16


1. Introducción
Se necesita usar punteros por:
– Si es necesario el paso por referencia de
un parámetro a una función.
– Si se usan datos de tamaño
desconocido en tiempo de
compilación.
– Si los programas manejan datos de
múltiples tipos.
– Si los programas utilizan listas
encadenadas de registros o de objetos.

Administración de Sistemas Informáticos 17/10/08 13:16


1. Introducción
 El espacio necesario para almacenar el dato asociado a la
variable, no se reserva en tiempo de compilación, por lo
que hay que recurrir a funciones especializadas que
realicen esta acción.
 En el caso de los vectores puede ocurrir que se reserve o
no, dependiendo del tipo de declaración que se realice.
– char texto[20]; //Reservada memoria para 20 variables de tipo
char;
– char texto[]; // No reserva memoria.
– char *texto; //No reserva memoria.
 Por tanto puede decidirse en tiempo de ejecución cuánta
memoria se necesita.

Administración de Sistemas Informáticos 17/10/08 13:16


1. Introducción
 Las funciones estándar de C que permiten
reservar y liberar bloques de memoria se
incluyen en stdlib.h y son las siguientes:
free() Permite liberar el espacio asignado previamente

malloc() Permite alojar un bloque de memoria

Permite alojar un bloque de memoria cuyos elementos se


calloc()
inicializan a 0

realloc() Permite volver a alojar un bloque de memoria

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Manejo de datos de tamaño desconocido
– Ejemplo.- Si se espera a reservar memoria
para una cadena sobre el heap en tiempo de
ejecución, se pueden asignar exactamente el
número de bytes necesarios para que quepa.
– Esto es un ejemplo trivial, pero en una
aplicación con cientos o miles de datos puede
marcar la diferencia entre funcionar o dar
error al quedarse sin memoria.

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 El heap

- El heap es toda la memoria que deja disponible


el sistema operativo y que no está siendo usada
por el código del programa, el segmento de datos
y el de pila (stack).

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Ejemplo memoria en tiempo de compilación

struct reg_alumno void LeerAlumno(struct reg_alumno *a)


{ {
char nombre[15]; printf(“Nombre del alumno: “);
char apellidos[25]; gets(a->nombre);
int edad; printf(“Apellidos: “);
}; gets(a->apellidos);
printf(“Edad: “);
scanf(“%d”,&a->edad);
}

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Ejemplo de memoria en tiempo de compilación

Si el usuario no rellena la estructura completamente, se estará


desperdiciando memoria; por ejemplo, si introduce los siguientes
datos:

E v a \0

G i l \0

23

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Memoria en tiempo de ejecución

- Evaluar en tiempo de ejecución cuánta memoria se necesita, y una


vez conocido el tamaño se pide mediante la función malloc():

- void *malloc(size_t size);


- La función malloc() devuelve un puntero al primer byte de una
región de memoria, asignada en el heap, cuyo tamaño en bytes es el
valor indicado en el parámetro size. Si no hay suficiente memoria en
la zona de memoria dinámica para satisfacer la petición, malloc()
devuelve un puntero nulo (valor NULL).

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Ejemplo memoria en tiempo de ejecución
struct reg_alumno Las cadenas se declaran como punteros que inicialmente
{ no apuntan a ninguna dirección válida.
char *nombre; La cadena aux contendrá la información real que se va a
almacenar en las cadenas. Por ejemplo, si aux contiene
char *apellidos;
“Eva”, el puntero nombre sólo necesita apuntar a una zona
int edad; de memoria con capacidad para almacenar 4 bytes.
};
nombre=(char *)malloc(4);
char aux[80];
Reservaría 4 bytes de memoria en una dirección del heap y
asignaría esa dirección al puntero nombre.

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Ejemplo memoria en tiempo de ejecución

? nombre

E v a \0 … aux

nombre=(char *)malloc((strlen(aux)+1)*sizeof(char)); // (4*1)

D11FF34 nombre
D11FF34
strcpy(nombre,aux);

D11FF34 nombre E v a \0
Administración de Sistemas Informáticos D11FF34 17/10/08 13:16
int LeerAlumno(struct reg_alumno *a) else
{ {
char aux[80]; strcpy(a->apellidos,aux);
printf("Nombre del alumno: "); printf("Edad: ");
gets(aux); scanf("%d",&a->edad);
a->nombre=(char *) fflush(stdin);
malloc((strlen(aux)+1)*sizeof(char)); return 0;
if (a->nombre==NULL) }
return 1; }
else }
{
strcpy(a->nombre,aux);
printf("Apellidos: ");
gets(aux);
a->apellidos=(char *) malloc
((strlen(aux)+1)*sizeof(char));
if (a->apellidos==NULL)
return 1;

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Liberar la memoria ocupada
El problema de la gestión dinámica es la no-destrucción por parte del
compilador de esa memoria cuando se acaba la validez de esa variable. El
compilador liberará la memoria ocupada por los punteros, pero no la
memoria a la que apuntan dichos punteros. Es decir, el programador es el
encargado de liberar esa memoria, por lo que se deberá implementar una
función que la libere totalmente, utilizando la función free(), cuyo prototipo
es el siguiente:

void free(void *block);


void DestruirAlumno(struct reg_alumno *a)
{
free(a->nombre);
free(a->apellidos);
}

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 realloc()
Suponiendo que hemos definido un vector de 20 elementos de la
siguiente forma:

int *v;
int tamanio = 20;
v = (int *) malloc (tamanio * sizeof(int));


0 1 2 3 19
v

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 realloc()

Si ahora necesitáramos un vector mayor, p.ej. de 25 elementos, habría que


volver a localizar una zona de memoria libre lo suficientemente grande como
para albergar, de forma consecutiva, los bytes necesarios para 25 enteros.
Esto se realiza con la función realloc():

void *realloc(void *block, size_t size);

donde block representa el vector actual y size el nuevo tamaño (en bytes)
necesario. La función, en caso de que no devuelva NULL, copiará todos los
datos de block en el nuevo vector dinámico.

tamanio = 25;
v = (int *) realloc (v, tamanio*sizeof(int));

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 Funcionamiento de realloc()

1 7 9 …
0 1 2 3 19

1 7 9 …
0 1 2 3 24

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 calloc()
– Funciona de la misma forma que malloc(), salvo que inicializa los elementos a 0.

– void *calloc(size_t nitems, size_t size);

– nitems será el número de elementos que se desea gestionar y size el número en


bytes que ocupa cada elemento.
– Por ejemplo, para asignar de forma dinámica espacio para un vector de 20 enteros
con valor inicial 0 se puede escribir:

v = (int *) calloc (20, sizeof(int));

– Al igual que malloc(), calloc() también devolverá un puntero NULL si no hay


memoria suficiente.

Administración de Sistemas Informáticos 17/10/08 13:16


2. Gestión dinámica de memoria
 calloc()
Suponiendo que hemos definido un vector de 20 elementos de la
siguiente forma:

int *v;
int tamanio = 20;
v = (int *) calloc (tamanio, sizeof(int));

0 0 0 0 0 0 …0
0 1 2 3 19
v

Administración de Sistemas Informáticos 17/10/08 13:16


3. Estructuras dinámicas de datos
 Cuando se procesan conjuntos de datos cuyo espacio de almacenamiento no
se puede predecir 'a priori' (en tiempo de compilación) y además la actividad
de los mismos (inserciones y borrados) es frecuente, las estructuras de datos
estáticas (los vectores) no son adecuadas para su implementación. Las
razones son varias:

– Los vectores deben ser declarados en tamaño en el programa fuente, de modo que
si se elige uno mayor que el necesario, entonces se malgasta espacio de memoria,
y si se hace pequeño, podría no ejecutarse el programa.

– La operación de añadir datos al final del vector es un proceso rápido; sin embargo,
las inserciones y eliminaciones en el interior del vector son lentas y complejas, ya
que puede ser necesario desplazar cada elemento del éste para hacer espacio al
nuevo elemento, o bien cerrar el espacio dejado por una eliminación.

 Si a esta dificultad se añaden los casos en que las operaciones anteriores sean
frecuentes, se puede deducir que en estos casos las estructuras más idóneas
son las estructuras dinámicas de datos.

Administración de Sistemas Informáticos 17/10/08 13:16


3. Estructuras dinámicas de datos
 Listas enlazadas
– Listas (inserción y borrado en cualquier lugar,
según clave)
– Pilas (inserción y borrado sólo por el final –LIFO
Last In, First Out-)
– Colas (inserción por el final, borrado por el
principio –FIFO First In, First Out-)
 Árboles

Administración de Sistemas Informáticos 17/10/08 13:16


4. Listas enlazadas
 Las listas enlazadas son una secuencia de nodos que se
encuentran enlazados cada uno con el siguiente mediante
un enlace o puntero. Cada elemento (nodo) de una lista
enlazada debe tener dos campos: un campo (información)
que contiene el valor de ese elemento y un campo (enlace
o puntero) que indica la posición del siguiente elemento.
 Los elementos de una lista están conectados o "enlazados"
mediante sus campos enlace o puntero.
 Los componentes de un nodo se llaman campos. Un nodo
tiene al menos un campo de datos o valor y un campo
enlace o siguiente. El campo enlace apunta (indica la
dirección) al siguiente nodo de la lista. Existe una marca
para fin de lista, que es la constante NULL.

Administración de Sistemas Informáticos 17/10/08 13:16


4. Listas enlazadas
struct nodo
{
struct nombre_estructura informacion;
struct nodo *siguiente;
};
 Si cada nodo únicamente tiene una referencia al nodo siguiente, se dice que
la lista está enlazada de forma simple. Cuando se tienen dos referencias,
una al nodo anterior y otra al siguiente, se dice que la lista está doblemente
enlazada. Los nodos de una lista doblemente enlazada tienen la siguiente
sintaxis:

struct nodo
{
struct nombre_estructura informacion;
struct nodo *siguiente;
struct nodo *anterior;
};

Administración de Sistemas Informáticos 17/10/08 13:16


4. Pilas y colas
Lo normal es que en una lista se inserten los elementos
siguiendo un criterio de ordenación por uno de sus
campos. Sin embargo, existen determinados casos en los
que el orden de inserción y borrado en una pila debe
cumplir unas características específicas:

 PILA.- El último elemento que insertamos en la lista


también es el primero que debe salir (estructura LIFO:
Last In,First Out).

 COLA.- El último elemento insertado es también el


último en salir, y el primero que insertamos debe ser el
primero en salir (estructura FIFO: First In, First Out).

Administración de Sistemas Informáticos 17/10/08 13:16

Vous aimerez peut-être aussi