Tema I P2profesores.fi-b.unam.mx/sfjc/Clase/Tema I_P2.pdf · 2020-03-04 · Microsoft PowerPoint -...

Preview:

Citation preview

MEMORIA DINÁMICA

Administración del almacenamiento en tiempo de ejecución

Un programa en C almacena sus datos en memoria en tres áreas diferentes:

Tipos de memoria en C

Memoria global: Se almacenan todos los datos queestán presentes desde el comienzo del programahasta que finaliza.

Pila: Área en la que las variables aparecen ydesaparecen, usada principalmente paraalmacenar variables locales a las funciones.

Heap: Contiene memoria disponible para reservary liberar en cualquier momento durante la ejecuciónde un programa. Es la memoria “dinámica”.

Tipos de memoria en C

La memoria global tiene un tamaño fijo y que sesabe cuando comienza la ejecución de unprograma.

La pila y el heap albergan datos cuyo tamaño nose puede saber hasta que el programa está enejecución.

Las áreas de la pila y el heap tienen un tamañovariable, el Sistema Operativo reserva un espacioinicial y las dos zonas crecen y decrecen dentro deese espacio.

Pila

El funcionamiento de una pila es como un espaciode anotación temporal.

En ella se almacenan las variables locales de unafunción, así también los parámetros de una función.

En la pila se crea espacio para las variables y sedestruye al acabar la función.

Heap y la memoria dinámica

La memoria dinámica que se almacena en el heapse utiliza para resguardar datos que se crean enmedio de la ejecución de un programa.

En C se solicita tanta memoria en bytes como seanecesaria, y una vez que ya no es requerida, sedevuelve (libera) la memoria para poder serreutilizada.

Hay cuatro operaciones en C para gestionar lamemoria: *malloc(), *calloc(), free() y*realloc() y se encuentran en stdlib.h

Funciones de gestión de memoria en C

void *malloc(size_t size)

La función reserva tantos bytes consecutivos de memoria como lo indica size. Devuelve la dirección de memoria de la porción reservada. La memoria no se inicializa a ningún valor.

void *calloc(size_t nmemb, size_t size)Reserva espacio para tantos elementos como lo indica nmemb, y cada uno de ellos con un tamaño de byte size. Devuelve la dirección de memoria y la función inicializa todos los bytes de la zona en cero.

Funciones de gestión de memoria en C

void free(void *ptr)

Función que dado un apuntador, libera el espaciopreviamente reservado. El apuntador que recibe comoparámetro tiene que ser el que ha obtenido con unallamada de reserva de memoria.

void *realloc(void *ptr, size_t size)Función que redimensiona una porción de memoriapreviamente reservada. La función devuelve ladirección de memoria de la nueva porciónredimensionada y el apuntador no necesariamenteigual al que se ha pasado como parámetro. Los datosse conservan.

Función sizeof()

La función recibe como parámetro el nombre de lavariable, o el nombre de un tipo de dato, ydevuelve el tamaño en bytes.

sizeof(int) devuelve el número de bytes paraalmacenar un entero.

La función también devuelve el tamaño en bytes detipos de datos estructurados o uniones

Llamadas a funciones de gestión de memoria

Para invocar a la función malloc se puede enunciarde la siguiente manera. El espacio en memoriadinámica para una variable tipo T se obtiene

T *ptr = (T *)malloc(sizeof(T));

Una vez que una estructura de datos reservada conmemoria dinámica no se necesita, se libera mediante lallamada a la función free.

free(ptr);

PILA

Estructura de datos compuestos

Estructuras de datos

Estructuras de Datos

Estáticas

Datos simples

Arreglos

Matrices

Dinámicas

Lineales

Pila

Cola

Listas

No lineales

Árboles

Grafos

Estructuras estáticas

En las estructuras anteriores, la capacidadmáxima de las colecciones deben definirsepreviamente.

Ejemplo: persona_t Persona[100];

El programa reserva una cantidad de memoriafija, más allá de que durante su ejecución lautilice o no.

Conjuntos dinámicos

Los conjuntos son manipulados poralgoritmos que pueden crecer, disminuir oque cambian con respecto a sus dimensionestodo el tiempo son conocidos como dinámicos.

Una conjunto dinámico típicamente serepresenta con un atributo que puedeexaminarse y manipularse; y un apuntador aotro elemento del conjunto.

Estructura dinámica

En programación, una estructura dinámica es laimplementación de un conjunto dinámico.

La colección de valores del mismo tipo puede variardurante la ejecución del programa aumentando odisminuyendo, en consecuencia, utilizando mayor omenor cantidad de memoria.

Se puede formar una estructura dinámica“enlazando” nodos.

Pilas y colas (Stacks & queues)

De manera abstracta, las pilas y las colas sonconjuntos dinámicos en donde el elemento eliminadodel conjunto por la operación Delete estápredefinido.

En una pila, el elemento eliminado del conjunto es elque más recientemente se insertó Last-In First Out oLIFO .

En una cola, el elemento eliminado es siempre elprimero que se insertó al conjunto First-In First-Outo FIFO

Operaciones en una pila

La operación Insert() de una pila es llamadapush(), y la operación Delete() que no tomaargumentos, es llamada pop()

Los nombres hacen alusión a una pila de platos en una cafetería.

Implementación de una pila

Con un arreglo

a) La pila S tiene 4 elementos. El último es el 9

b) La pila después de la operación push(S,17) y push(S,3).

c) La pila después de pop(S) el cual regresa 3, el 3 aparece en el arreglo pero ya no en la pila.

Underflows y overflows

Cuando la pila no contiene elementos, la pila está vacía empty.

Si se efectúa un pop sobre la pila vacía, se dice que la pila subdesborda (underflows) y esto normalmente es un error.

Si la cantidad de elementos excede la capacidad de la pila, se dice que la pila desborda (overflows)

Pseudocódigo de las operaciones de una pila

empty(S)if S.top==0 return TRUE

elsereturn FALSE

push(S,x)if S.top == MAX

error “overflow”else

S.top = S.top +1S[S.top] = x

pop(S)if empty(S)

error “underflow”else

v = S[S.top] S.top = S.top-1

return v

PILA de forma dinámica

El nodo implementado en C

Un nodo representa un conjunto de uno o más valores,más un apuntador haciendo referencia al siguientenodo de la colección.

typedef struct nodo{int valor;struct nodo* sig;

} nodo_t;

nodo_t *apNodo;

valor sig

apNodo

Implementación de la pila con memoria dinámica

Agregar los elementos {3,2,1} en una pila. Definimos un apuntador p de tipo nodo_t* e inicializado en

NULL

nodo_t *p = NULL; Agregamos al inicio de la estructura apuntada por p los

elementos {3,2,1}, iniciando con 3, push(&p,3);

Agregamos el segundo elemento, push(&p,2);3 x

2 3 x

p

p

Implementación con memoria dinámica

Agregamos el 1, push(&p,1);

Luego para sacar un elemento de la pila, tomaremos el primero de la estructura definida.

Veamos el diagrama y la codificación de las funciones y una manera de definir la pila vacía

1 2 3 Xp

Push

void push(nodo_t** p, int v){

nodo_t* nuevo = (nodo_t*) malloc(sizeof(nodo_t));nuevo->valor = v;nuevo->sig = *p;*p = nuevo;

}

nodo_t *nuevo = (nodo_t*)malloc(sizeof(nodo_t))

nuevo->valor = v

nuevo-> sig = *p

*p = nuevo

Pop y empty

int pop(nodo_t** p){

nodo_t* aux = *p;int ret = aux->valor;*p = aux->sig;free(aux);return ret;

}

int empty(nodo_t* p){

return p == NULL;}

aux = *p

ret = aux -> valor

*p = aux -> sig

return ret

free(aux)

COLA (QUEUE)

Estructura de datos compuestos

Colas

La operación Insert() en una cola es llamada enqueue y la operación Delete de la cola dequeue

Una analogía de la estructura FIFO (First-In First-Out) es la fila para pasar a pagar en el super

Operaciones en una cola

Pensando en las colas como un conjuntodinámico, la operación de Insert() esenqueue (como el push de una pila) y laoperación Delete() es dequeue.

Se reconoce a estas operaciones como encolary desencolar aunque coloquialmente es másnatural decir “formarse en la fila” y “salir dela fila (de las tortillas o del super)”

Implementación de una cola estática (circular).

Usando arreglos

Los elementos de la cola Q aparecen más claros.

La cola tiene dos apuntadores, uno que marca el inicio head y uno que marca el final tail

a)la cola Q tiene 5 elementos: Q[7..11]

Implementación de una cola estática (circular)

b) La cola muestra el resultado de enqueue(Q,17), enqueue(Q,3) y enqueue(Q,5).

c) Vemos el resultado de la operación dequeue(Q) que devolvería el 15

Underflow y overflow

Una similitud de la cola con una pila es el error quese presenta al no tener elementos almacenados oexceder de ellos.

Los apuntadores head y tail serían iguales enambos casos de error, cuando no hay elementos(underflow) y cuando exceden el almacenamiento(overflow).

Pseudocódigo de enqueue y dequeue(circular)

Enqueue(Q,x)Q[Q.tail]=xif Q.tail== Q.length

Q.tail = 1else

Q.tail=Q.tail+1

Dequeue(Q)x=Q[Q.head]if Q.head == Q.length

Q.head = 1else

Q.head = Q.head+1return x

Implementación de la cola con memoria dinámica

De vuelta a la cola del super, la gente que llega ala cola se ubica al final. La cajera atiende alprimero, y ese cliente se retira para dejar su lugaral segundo y así sucesivamente.

Utilizaremos una estructura con dos apuntadores:uno al primer nodo del conjunto y uno al último.

Luego para enqueue() un elemento lo agregamos alfinal del conjunto y para dequeue() eliminamos alprimero de la lista.

Estructuras para el uso de queue

typedef struct nodo{

int valor;struct nodo *sig;

} nodo_t;

typedef struct queue{

nodo_t *head;nodo_t *tail;

} queue_t;

enqueue

void enqueue( queue_t *q , int v){

nodo_t *nuevo = (nodo_t *)malloc(sizeof(nodo_t));

nuevo->valor = v;nuevo->sig = NULL;

if(q->head == NULL && q->tail== NULL){

//primer elemento de qq->head = nuevo;q->tail = nuevo;

}else{

q->tail->sig = nuevo; // Enlazar el nuevo nodoq->tail = nuevo; // Recorre Tail al ultimo nodo

}}

dequeue

int dequeue( queue_t *q ){

int v_retorno = 0;nodo_t *aux;

if(q->head != NULL && q->tail != NULL ){

v_retorno = (q->head)->valor;aux = q->head;

if(q->head == q->tail){

// coloca los apuntadores a nulo// debido a que se trata del ultimo elementoq->head = NULL;q->tail = NULL;

}

dequeue (continuación)

else{// mover el apuntador headq->head = aux->sig; // q->head=(q->head)->sig;}free(aux);

}else{

printf("Q vacia, error de underflow \n");}

return v_retorno;}

crearQueue()

Cola circular

La cola circular es una mejora de la cola simple, debido a que es

una estructura de datos lineal en la cual el siguiente elemento del

último es, en realidad, el primero. La cola circular utiliza de

manera más eficiente la memoria que una cola simple.

Debido a que una cola circular es una mejora de la cola simple,

maneja las mismas operaciones para INSERTAR (ENCOLAR) y

ELIMINAR (DESENCOLAR).

Cola circular

Cuando se inserta un nodose verifica si el número deelementos que tiene laestructura es menor alnúmero máximo deelementos definidos, si esasí, existe espacio y elnuevo nodo se puedeinsertar, si el apuntador Tailse encuentra en la posiciónMAX , el apuntador Tail seasigna en la posición 1 dela estructura.

queue (circular)

typedef struct nodo { int valor; struct nodo* sig; //referencia al sig nodo } nodo_t; typedef struct queue { nodo_t *tail; } queue_t;

enqueue (circular)

void enqueue( queue_t *q, int v) {

nodo_t *nuevo = (nodo_t *)malloc(sizeof(nodo_t));nuevo->valor = v;

if( empty(q) ) {// Primer nodo nuevo->sig = nuevo;

} else {nuevo->sig = q->tail->sig;q->tail->sig = nuevo;// Enlazar el nuevo nodo

}q->tail = nuevo;

}

dequeue (circular)

int dequeue( queue_t *q ){

int v_retorno = 0;nodo_t *aux;if( empty(q) ) {

printf("Q vacia, error de underflow \n");} else {

v_retorno = (q->tail->sig)->valor;aux = q->tail->sig;if(aux == q->tail) {

q->tail = NULL;} else {

q->tail->sig = aux->sig;}

free(aux);}return v_retorno;}

empty

int empty( queue_t *q ) {

return q->tail == NULL? 1:0;

}

Implementación funcional de una cola

A continuación se muestra un ejemplo del funcionamiento de una colaint main() {

queue_t *q = crearQueue();//encolamos varios elementos enqueue(q,1);enqueue(q,2);enqueue(q,3);//desencolamos un elemento (sale el 1) printf("%d\n",dequeue(q));//desencolamos un elemento (sale el 2) printf("%d\n",dequeue(q));//encolamos mas elementos

return 0;}

Cola doble

Una cola doble (o bicola) es una estructura de datos tipocola simple en la cual las operaciones ENCOLAR yDESENCOLAR se pueden realizar por ambos extremos dela estructura, es decir, en una cola doble se puedenrealizar las operaciones:

Encolar por Head Desencolar por Head Encolar por Tail Desencolar por Tail

Cola doble

Recommended