estructuras lineales

60
Programación II Mauricio Paletta Coordinación General de Pregrado UNIVERSIDAD NACIONAL EXPERIMENTAL DE GUAYANA INGENIERÍA EN INFORMÁTICA Programación II Estructuras de Datos Lineales Presentación

Upload: karlalopezbello

Post on 18-Nov-2014

2.370 views

Category:

Documents


2 download

DESCRIPTION

Estructuras lineales | Lenguaje C++ | Profesor Mauricio Paletta

TRANSCRIPT

Page 1: Estructuras lineales

Programación II

Mauricio Paletta

Coordinación General de Pregrado

UNIVERSIDAD NACIONAL EXPERIMENTAL DE GUAYANA

INGENIERÍA EN INFORMÁTICA

Programación II

Estructuras de Datos Lineales

Presentación

Page 2: Estructuras lineales

Programación II

Introducción

La memoria se puede ver como una gran

matriz de celdas, cada una de las cuales

representa un byte de información y tiene

asociado un único número o dirección a la

cual se le puede llegar directamente.

Una interesante analogía de este concepto lo

es un conjunto de casilleros postales

agrupados matricialmente. El contenido del

casillero es el byte de información. El número

(llave) es la dirección.

Page 3: Estructuras lineales

Programación II

Introducción

Page 4: Estructuras lineales

Programación II

Introducción

Cada vez que se declara algo (variable,

constante, función, estructura, etc.) esta

declaración debe tener asociado un conjunto

de celdas de la matriz de memoria de tantos

bytes como requiera la declaración.

Para cualquier declaración es importante

saber cómo se accede o se obtiene:

1) La data (contenido del buzón).

2) La dirección (llave o número del buzón).

Page 5: Estructuras lineales

Programación II

Introducción

Según el momento en el cual se solicita la

memoria, esta solicitud puede ser:

1) Estática (tiempo de compilación).

2) Dinámica (tiempo de ejecución).

La asignación de memoria se puede hacer de

dos maneras:

1) Continua o lineal.

2) No continua o no lineal.

Page 6: Estructuras lineales

Programación II

Solicitudes estáticas

Ocurre en tiempo de compilación del

programa. El compilador sabe exactamente

la cantidad de bytes que se requieren para

satisfacer la declaración y se procede a hacer

la reserva del espacio.

Ejemplo:

int I;

double D;

Page 7: Estructuras lineales

Programación II

Solicitudes estáticas

En cualquier declaración de tipo básico (int,

double, char, bool, etc.) el identificador de la

declaración representa el contenido o dato

(buzón). Para obtener la dirección (llave /

número del buzón) se hace uso del operador

unario &.

Ejemplo:

double D; D es la data

&D es la dirección

Page 8: Estructuras lineales

Programación II

Solicitudes estáticas

D

data

… …

&D

dirección

Cantidad de bytes necesarios

para representar/almacenar un

dato de tipo double

sizeof(double)

Page 9: Estructuras lineales

Programación II

Solicitudes dinámicas

Ocurre en tiempo de ejecución del programa.

Se hace uso del operador de reserva de

memoria new. Este operador retorna una

dirección de memoria o apuntador, por lo que

se requiere declarar un apuntador para recibir

lo que el operador new retorna.

Para declarar apuntadores de memoria se

hace uso del símbolo *.

Page 10: Estructuras lineales

Programación II

Solicitudes dinámicas

Ejemplo:

int *pI;

double *pD;

En cualquier declaración de tipo básico, si se

tiene una dirección de memoria (apuntador),

el operador * permite obtener la data

almacenada en el espacio de memoria a la

cual el apuntador apunta.

Page 11: Estructuras lineales

Programación II

Solicitudes dinámicas

*pD

data

… …

pD

dirección

Ejemplo:

double *pD = new double();

Uso del operador new para

reserva dinámica de memoria

Page 12: Estructuras lineales

Programación II

Solicitudes dinámicas

D = *pD

data

… …

&D = pD

dirección

Ejemplo:

double D, *pD = &D;

Los apuntadores no sólo son utilizados para

hacer reserva dinámica de memoria

Page 13: Estructuras lineales

Programación II

Solicitudes dinámicas

En C++ el programador es responsable de

cualquier espacio de memoria que se reserva

dinámicamente con el operador new. Una

vez que el espacio no es más requerido, se

debe hacer una liberación del espacio para

que éste pueda ser reutilizado por otros

usuarios. Para ello se hace uso del operador

delete.

Page 14: Estructuras lineales

Programación II

Solicitudes dinámicas

Ejemplo:

int *pI = new int();

delete pI;

NOTA: Si por alguna razón la reserva de

espacio de memoria no es posible (por

ejemplo cuando no hay más memoria

disponible), el operador new retorna una

dirección nula no válida equivalente a 0L.

Page 15: Estructuras lineales

Programación II

Solicitudes dinámicas

NOTA: Los apuntadores son un tipo particular

de declaración que también requieren de un

espacio de memoria para su representación

y almacenamiento. Este espacio es

equivalente al tipo de dato long. Esa es la

razón porque un apuntador nulo es igual al

literal 0L.

Hay que tener cuidado de no hacer un

delete con una dirección de memoria no

válida.

Page 16: Estructuras lineales

Programación II

Solicitudes dinámicas

Ejemplo:

char *pC = new char(„A‟);

if (pC == 0L) {

cout << “Posible problema de memoria”;

return;

}

delete pC;

Page 17: Estructuras lineales

Programación II

Estructuras continuas / lineales

Son aquellas que ocupan un espacio de

memoria (bloque) continuo (un byte al lado

del otro).

Todas las declaraciones de tipos básicos son

lineales, tanto si se reservan de manera

estática como de manera dinámica.

Es necesario tener una dirección de memoria

que permita llegar al bloque donde está la

estructura.

Page 18: Estructuras lineales

Programación II

Estructuras continuas / lineales

Ventajas:

1) Sólo se requiere una dirección de memoria

para llegar al bloque acceso fácil a la

información.

2) Una vez que se llega al bloque toda la data

está accesible acceso rápido a la

información.

Page 19: Estructuras lineales

Programación II

Estructuras continuas / lineales

Desventajas:

1) Es necesario conocer, ya sea en tiempo

estático o dinámico, el número de bytes que

se requiere para reservar el bloque su

tamaño es estático, no puede crecer.

2) Para bloques de gran tamaño, es posible que

se de el caso de no encontrar un espacio

continuo lo suficientemente grande para

satisfacer la necesidad (aún habiendo

memoria disponible) posibles problemas

de reserva de memoria.

Page 20: Estructuras lineales

Programación II

Estructuras continuas / lineales

NOTA: Las estructuras continuas son

susceptibles al problema de fragmentación

de memoria aún habiendo varios bytes

de memoria disponibles, la alternación de

bloques ocupados y libres hace que los

espacios continuos sean más pequeños de

los que se necesitan.

Page 21: Estructuras lineales

Programación II

Estructuras continuas / lineales

Page 22: Estructuras lineales

Programación II

Estructuras continuas / lineales

Dos clases de estructuras:

1) Arreglos: conjunto finito de elementos del

mismo tipo.

2) Registros: conjunto finito de elementos de

tipo diferente.

Page 23: Estructuras lineales

Programación II

Arreglos

Para su definición / declaración se requieren

tres cosas:

1) Conocer el tipo de dato único de todos sus

elementos.

2) Conocer la cantidad de elementos del

conjunto.

3) Dar un identificador válido para acceder a los

elementos del conjunto.

Page 24: Estructuras lineales

Programación II

Arreglos

Ejemplo:

char Cadena[10];

Cadena es un arreglo de 10 elementos de

tipo char. Cadena es también la dirección de

memoria del espacio continuo donde se

almacenan los 10 elementos.

Para acceder a los elementos del arreglo se

hace uso de un índice que indica la posición

del elemento en el conjunto.

Page 25: Estructuras lineales

Programación II

Arreglos

En C++ el primer elemento se encuentra en

la posición 0; para el ejemplo anterior, el

último elemento está en la posición 9.

Los elementos de un arreglo se almacenan

en memoria uno al lado del otro de acuerdo a

su posición y conforme a la cantidad de bytes

que ocupa cada elemento.

Los arreglos también pueden ser inicializados

en tiempo de declaración.

Page 26: Estructuras lineales

Programación II

Arreglos

V[0] = 10

… …

V

dirección

Ejemplo:

int V[3] = { 10, 20, 30 };

Inicialización en tiempo de declaración

V[1] = 20 V[2] = 30

sizeof(int)

Page 27: Estructuras lineales

Programación II

Arreglos

Nótese que *V y V[0] son lo mismo. En

general, *(V+i) y V[i] son lo mismo.

Para estimar el número de bytes que ocupa

la estructura en memoria basta multiplicar el

número de elementos por el tamaño en bytes

del tipo de dato de cada elemento. Para el

ejemplo anterior:

3 x sizeof(int) sizeof(V)

Page 28: Estructuras lineales

Programación II

Arreglos

¿Qué hacer cuando no se conoce a priori

(estáticamente) el número de elementos? Por

ejemplo cuando se tiene que leer durante la

ejecución del programa.

Hay que hacer reserva de espacio dinámica

de memoria usar un apuntador o dirección

de memoria y los operadores new y delete.

Page 29: Estructuras lineales

Programación II

Arreglos

Page 30: Estructuras lineales

Programación II

Arreglos

Nótese que no es posible hacer:

double V[N];

A menos que N sea una constante

previamente definida:

const int N = 10;

O una macro previamente definida:

#define N 10

Page 31: Estructuras lineales

Programación II

Arreglos

Page 32: Estructuras lineales

Programación II

Arreglos

¿Cómo representar arreglos de más de una

dimensión: matrices por ejemplo?

1 dimensión vector

2 dimensiones matriz bidimensional

3 dimensiones matriz tridimensional

N dimensiones matriz híper-espacial

Se agrega otro tamaño y se usa otro índice

para cada nueva dimensión.

Page 33: Estructuras lineales

Programación II

Arreglos

Fila 0M

dirección

Ejemplo:

char M[2][2] = { { „A‟, „B‟ }, { „C‟, „D‟ } };

Inicialización en tiempo de declaración

Fila 1

M[0

][0

]

M[0

][1]

M[1

][0]

M[1

][1]

„A‟ „B‟ „C‟ „D‟

Page 34: Estructuras lineales

Programación II

Arreglos

Nótese que *M y M[0][0] son lo mismo. En

general, *(M+2*i+j) y M[i][j] son lo mismo.

Para estimar el número de bytes que ocupa

la estructura en memoria basta multiplicar el

número de elementos de cada dimensión por

el tamaño en bytes del tipo de dato de cada

elemento. Para el ejemplo anterior:

2 x 2 x sizeof(char) sizeof(M)

Page 35: Estructuras lineales

Programación II

Arreglos

Page 36: Estructuras lineales

Programación II

Arreglos

Para hacer la reserva dinámica de espacio en

arreglos de más de una dimensión se hace

uso igual de apuntadores y los operadores

new y delete.

En algunas versiones del lenguaje NO es

posible hacer:

double *V = new double[N][M];

Page 37: Estructuras lineales

Programación II

Arreglos

Page 38: Estructuras lineales

Programación II

Arreglos

Page 39: Estructuras lineales

Programación II

Arreglos

Otra solución es hacer vectores enlazados:

Dirección

del arreglo

Vector de F

apuntadores

F Vectores de

C elementos

[0][

0]

[0][

1]

[0][

C-1

]

[1][

0]

[1][

1]

[1][

C-1

]

[F-1

][0]

[F-1

]

[C-1

]

[F-1

][1]

Page 40: Estructuras lineales

Programación II

Arreglos

Page 41: Estructuras lineales

Programación II

Registros

Para su definición / declaración se requieren

tres cosas:

1) Conocer el tipo de dato posiblemente

diferente de cada uno de sus elementos.

2) Conocer el identificador único y válido de

cada uno de sus elementos.

3) Dar un identificador válido para acceder a los

elementos del conjunto.

Page 42: Estructuras lineales

Programación II

Registros

En C++ se reconocen tres tipos de registros:

1) Estructuras: derivadas del lenguaje C. Se

hace uso de la palabra reservada struct.

2) Registros invariantes (union): derivadas del

lenguaje C. Se hace uso de la palabra

reservada union.

3) Clases: agregadas en C++ para la

programación orientada a objetos. Se hace

uso de la palabra reservada class.

Page 43: Estructuras lineales

Programación II

Registros

Los registros pueden incluir tanto datos como

métodos y se almacenan en memoria un

elemento al lado del otro en el mismo orden

secuencial en el cual están definidos.

Para el caso de los métodos la memoria

correspondiente tiene el código del método ó

la dirección donde está el código

dependiendo si la definición es inline ó outline

respectivamente.

Page 44: Estructuras lineales

Programación II

Registros

Las estructuras y registros invariantes, al

igual que las clases, poseen declarativas de

interfaz (public, protected, private). Si no se

dice nada por defecto los elementos son

públicos.

Para acceder a los elementos se hace uso

del operador „.‟ si se trata de una variable /

objeto ó el operador „->‟ si se trata de una

dirección de memoria.

Page 45: Estructuras lineales

Programación II

Registros

Al igual que se hace con los datos básicos,

para acceder a la dirección de memoria

teniendo una variable / objeto declarado se

hace uso del operador „&‟.

Las estructuras y registros invariantes se

pueden anidar (definir en cascada uno dentro

del otro); las clases no.

Page 46: Estructuras lineales

Programación II

Registros

Ejemplo:

struct Tstr {

int I;

double D;

char C;

Tstr() {

I = 0; D = 0.0; C = „\0‟;

}

};

typedef Tstr *pTstr;

Page 47: Estructuras lineales

Programación II

Registros

Tstr st;

pTstr stp = &st;

st.I = 2;

stp->D = 2.0;

st.I stp->I

= 2

… …

&st stp

dirección

st.D stp->D

= 2.0

st.C stp->C

= „1‟

sizeof(double)sizeof(int) sizeof(char)

st.Tstr()

stp->Tstr()

Page 48: Estructuras lineales

Programación II

Registros

Para obtener el número de bytes del bloque

de memoria que ocupa un registro basta

aplicar el operador sizeof al tipo de dato que

se define implícitamente o la variable / objeto

correspondiente. Para el caso anterior:

sizeof(Tstr) sizeof(st) sizeof(*stp)

Nótese que no es lo mismo sizeof(stp) que

sizeof(*stp); el primero es el número de bytes

que requiere un apuntador.

Page 49: Estructuras lineales

Programación II

Registros

Ejemplo:

struct Tiempo {

struct Fecha {

int D, M, A;

} Fec;

struct Hora {

int H, M, S;

} Hor;

} t = { { 12, 8, 2010 }, { 11, 48, 0 } };

Page 50: Estructuras lineales

Programación II

Registros

La única característica que diferencia los

registros invariantes (union) de las

estructuras (struct) es que en los primeros

todos los elementos ocupan el mismo

espacio de memoria.

Son útiles para administrar una misma data

(memoria) haciendo uso de tipos de dato

diferentes.

Page 51: Estructuras lineales

Programación II

Registros

0xA

A

&u

dirección u.c

[0]

sizeof(short) =

2 x sizeof(char)

0xB

Bu

.c[1

]

Page 52: Estructuras lineales

Programación II

Registros

El número de bytes de un registro invariante

coincide con el número de bytes del elemento

que más bytes ocupa en la estructura.

Todos los elementos se organizan en

memoria de forma tal que empiezan

exactamente con el primer byte de la

estructura.

Page 53: Estructuras lineales

Programación II

Estructuras complejas

Está claro que puede haber combinación de

arreglos de arreglos, registros de registros,

arreglos de registros y registros de arreglos.

Es importante tener claro:

1) La manera como se organizan en el bloque de

memoria.

2) La manera de obtener la dirección de memoria

al bloque.

3) La manera en la que se accede a todos los

elementos.

Page 54: Estructuras lineales

Programación II

Estructuras complejas

Cada vez que se consigue en el camino un

arreglo, se requieren tantos índices como

dimensiones tenga el arreglo para acceder al

elemento y se hace uso del operador de

direccionamiento „[ ]‟.

Cada vez que se consigue en el camino un

registro, se requiere el operador „.‟ para

acceder al elemento que se desee.

Page 55: Estructuras lineales

Programación II

Estructuras complejas

Page 56: Estructuras lineales

Programación II

Estructuras complejas

STR2

VSTR1

dirección

dSTR1

cSTR2

2 x

sizeof(double)sizeof(int)

4 x

sizeof(char)

iSTR2

STR1

VSTR1[0]V

ST

R1

[1]

VS

TR

1[2

]

sizeof(STR1)

3 x sizeof(STR1) = sizeof(VSTR1)

Page 57: Estructuras lineales

Programación II

TAD particulares

1) Conjuntos finitos hasta un máximo de

elementos y sus respectivas operaciones:

agregar, suprimir, pertenencia,

cardinalidad, unión, intersección,

diferencia, lleno, vacío.

2) Pilas: conjuntos particulares cuyas

operaciones de agregación/supresión

siguen el algoritmo LIFO (Last In First Out

– último en entrar, primero en salir).

Page 58: Estructuras lineales

Programación II

TAD particulares

3) Colas: conjuntos particulares cuyas

operaciones de agregación/supresión

siguen el algoritmo FIFO (First In First Out

– primero en entrar, primero en salir).

4) Dipolo: colas en los dos sentidos dos

operaciones de agregación y dos

operaciones de supresión.

Page 59: Estructuras lineales

Programación II

TAD particulares

3) Buffer circular: Se maneja como una cola

pero no hay límite sobre los elementos a

agregar. Primeros elementos agregados

pueden ser reemplazados por nuevos

elementos si la velocidad de agregación es

mayor que la de supresión.

Page 60: Estructuras lineales

Programación II

TAD particulares