Unidad 3: Estructuras de Datos.hot!

Anuncio
Unidad III. Estructuras de Datos.
Objetivos
Adquirir los conceptos básicos referente a estructura de datos.
Conocer las principales estructuras de datos, desde un punto de vista
abstracto, y sus formas de representación, así como las operaciones que se
puedan realizar sobre ellas.
Aplicar todos los conceptos adquiridos mediante resolución de supuestos
prácticos siendo capaces de elegir siempre la representación más eficiente.
Aplicar y adaptar las estructuras de datos a nuevos requisitos de operación y
representación de información.
Tema I. Definición, características y ventajas
Definición de Estructura de Datos
Una estructura o registro es un conjunto de variables que pueden ser agrupadas y
tratadas como si fuesen una sola. Este conjunto puede estar compuesto de
variables de cualquier tipo, inclusive de otras estructuras. Una estructura,
generalmente, define un nuevo tipo de dato.
Semánticamente, una estructura agrupa datos que tienen alguna relación según
un cierto criterio.
Imagine que se desea almacenar los datos de un estudiante y sus notas. Todo
esto puede ser agrupado en una estructura que podríamos llamar:
DatosEstudiante , que de forma práctica define un nuevo tipo de dato.
Ejemplo
struct DatosEstudiante
{
char cedula[12];
char nombre[32];
char telefono[10];
int notaPrimerParcial;
int notaSegundoParcial;
};
Tema II. Forma de una Estructura de Datos
Tiene la forma de todos sus componentes pero serializados. La serialización
consiste en la juntura de todos los contenidos de las variables de un registro,
uno detrás del otro.
Hay un caso especial que distinguir: cuando hay punteros en la estructura.
Ve por qué? Piense en el contenido de una variable puntero.
Ventajas
•
•
•
Mejor organización del código, más expresividad y en consecuencia un
mejor código.
Acorta el tamaño del código para hacer asignaciones de estructuras
completas. Ej: estudiante1 = estudiante2. Donde ambas variables son
del tipo RegistroEstudiante.
Pueden ser pasadas por parámetro y ocurren copias, inclusive de
arreglos, al menos con el compilador de GNU.
Tema III. Sintaxis
Sintaxis Algoritmica
La notación algorítmica de una estructura es:
Estructura
{
tipo1 dato1;
tipo2 dato2;
…
tipon daton;
}
Una propiedad interesante del tipo de dato estructura es que pueden
anidarse otras “Estructuras” indefinidamente.
Sintaxis en C
struct punto {
int x;
int y;
}; // observe el punto y coma al final.
El nombre de la estructura es “punto” y tiene como miembros un par de
variables enteras: “x” e “y”.
Podemos declarar una o mas variables del tipo estructura de la siguiente
manera:
struct {
int var1;
float var2;
} i, j, k;
Notese que i, j y k son declaradas análogamente como si lo hiciéramos con
cualquiera de los tipos conocidos.
Una vez definida la estructura, pueden hacerse sucesivas declaraciones:
struct point w;
Y también puede utilizarse la inicialización con llaves:
struct point h = {10, 20}; // coordenadas (10,20).
Tema IV. Operadores sobre Estructuras (Anidamiento,
Arreglos, Punteros, ...)
Anidamiento de Estructuras
Las estructuras pueden estar anidadas unas dentro de otras:
struct point {
int x;
int y;
};
struct triangle {
struct point p1, p2, p3;
} t;
int main()
{
// En algún lugar dentro del programa
t.p1 = {4, 6};
t.p2.x = 20;
t.p2.y = 32;
t.p3.x = t.p2.x – 10;
t.p3.y = t.p3.y + t.p3.x;
return 0;
}
Anidamiento de Estructuras
Las estructuras pueden estar anidadas unas dentro de otras:
struct point {
int x;
int y;
};
struct triangle {
struct point p1, p2, p3;
} t;
int main()
{
// En algún lugar dentro del programa
t.p1 = {4, 6};
t.p2.x = 20;
t.p2.y = 32;
t.p3.x = t.p2.x – 10;
t.p3.y = t.p3.y + t.p3.x;
return 0;
}
Pase de Estructuras como Parámetros
Las estructuras al igual que las variables simples, pueden ser pasadas por
parámetro a cualquier función.
struct recta {
float m; //pendiente
float b; // termino independiente
};
float area_triagulo (struct triangle ta)
{
float base = longitud(ta.p1, ta.p2);
struct recta r1 = ec_recta_perpendicular(ta.p1, ta.p2, ta.p3);
struct recta r2 = ec_recta(ta.p1, ta.p2);
struct point p_i = interseccion(r1, r2);
float altura = longitud(p_i, p3);
return (base * altura) / 2;
}
Arreglos de Estructuras
Una manera de resolver los arreglos de estructuras es a través de arreglos
paralelos.
cadena nombres[n];
cadena apellidos[n];
…
entero primerParcial[n];
Punteros a Estructuras
Las estructuras también pueden ser trabajadas a través de su dirección de
memoria.
struct RegistroEstudiante * pre;
struct RegistroEstudiante reg1;
reg1.nombre = “Fernando”;
reg1.apellido = “Corbato”;
pre = &reg1;
pre->notaPrimerParcial = 20;
// el operado de indirección -> sirve para acceder
// los miembros de una estructura a través de un
// puntero.
Ejemplo 1
Suponga el siguiente caso de una estructura que tiene un apuntador a una
estructura de su mismo tipo.
struct bloque {
int a;
float b;
struct bloque * s
};
Observe que s es un apuntador a estructura del tipo struct bloque.
Ejemplo 2
Como se obtendrian un par de estructuras enlazadas?
struct bloque bl1;
struct bloque bl2;
bl2.s = &bl1;
Luego, que puedo hacer con bl1 desde bl2?
bl2.s->a = 145; // a pertenece a bl1
cout << bl1.a; // imprime 145...
Estructuras y Funciones
struct trickyStruct
{ int longArray[10000]; };
void f1(trickyStruct ts);
void f2(trickyStruct *ts);
void f3()
{ struct trickyStruct p;
// cualquier operacion para llenar p
f1(p); // copia todo
f2(&p); // solamente pasa la direccion, nos ahorramos 9999 copias...
}
Tema V. Tipos Abstractos de Datos
Definición de Abstracción de Datos.
La abstracción de datos se refiere la extracción de las supracaracterísticas de
un objeto en particular.
La abstracción consiste en enfocar los aspectos esenciales inherentes a una
entidad e ignorar las propiedades accidentales.
Un tipo de dato abstracto, no posee instancia. Como diría Platón: es la idea
del objeto.
Ejemplo
Para comprender mejor un tipo de dato abstracto, podriamos citar la idea (o
abstracción) de poligono.
Un polígono es una figura geométrica plana, compuesta por lineas rectas que
se tocan en puntos extremos.
Con un polígono podemos hacer las operaciones: rotar, area, perímetro.
Abstracción como proceso
Consiste en separar las propiedades esenciales de un objeto, sistema, fenómeno
o problema y omitir las propiedades no esenciales.
Abstracción como producto
Es una descripción o especificación de un sistema en el que se enfatizan
algunos detalles o propiedades y se suprimen otros.
Una abstracción como producto nos dice que un objeto puede poseer partes
que pueden ser refinadas a posteriori.
Es importante destacar que las propiedades esenciales de un sistemas son
tratadas como un todo.
Ejemplo
Suponga que se tiene la clase persona:
class persona {
protected:
char nombre[20];
char apellido[20];
char edad;
public:
virtual void pago_pasaje() { ... }
};
class estudiante : public persona {
public:
void pago_pasaje() { // otro procedimiento }
};
Tipo de Dato Abstracto
Un TDA es un tipo de dato definido por el programador que se puede
manipular de un modo similar a los tipos de datos definidos por el sistema.
Está formado por un conjunto válido de elementos y un número de
operaciones primitivas que se pueden realizar sobre ellos.
Tipos básicos de operaciones en un TDA
Constructores: Crean una nueva instancia del tipo.
Transformación: Cambian el valor de uno o más elementos de una instancia
del tipo.
Observación: Nos permiten observar el valor de uno o varios elementos de
una instancia sin modificarlos.
Iteradores: Nos permiten procesar todos los componentes en un TDA de
forma secuencial.
Implementacion
Cuando ya se tiene bien diseñado un Tipo Abstracto, el siguiente paso es
decidir una implementación para el mismo. Esto implica escoger unas
estructuras de datos para representar cada uno de los objetos abstractos y
escribir una rutina(Procedimiento o función) en un lenguaje de programación,
que simule el funcionamiento de cada una de las operaciones de acuerdo
con su especificación. La selección de las estructuras de datos determina, en
muchos casos, la complegidad del algoritmo que implementa una operación y
es, por esta razón, de gran importancia su escogencia. Existen estructuras de
datos muy dependientes de un lenguaje de programación y debido a esto
deben trata de evitarse cuando el TAD se quiere hacer portable.
Propiedades de los TAD
Encapsulación: Consiste en poder esconder datos y operaciones poco
relevantes para la interfaz del objeto. Se imagina que para poder ver
tuvieramos conciencia de todo el proceso de la visión?
Generalización: Como se dijo antes, un TAD trata de representar las
características escenciales de un objeto.
Polimorfismo: Es una propiedad que permite tener distintas conductas para
una misma función.
Ejemplo
class Estudiante {
public:
float calculo_matricula()
};
class Estud_Pregrado : public Estudiante {
public:
float calculo_matricula()
};
Aquí no hay duda, la función calculo_matricula será invocada dependiendo
del tipo del objeto. Existe un reemplazo en tiempo de compilaci'on de una
función por la otra en la clase derivada.
Tema VI. TDA Pilas
Definición
Es una colección lineal, dinámica y homogénea, en la que los elementos de
insertan y se extraen por el mismo extremo.
También conocida como estructura LIFO (Last In, First Out).
Operaciones
CrearPila
Meter
Sacar
DestruirPila
EstaVacia
Representación
Utilizaremos un array para representar la pila.
Definiremos un tamaño máximo de array (MaxElemPila).
Llevaremos una variable: cima que indicará cual es el último elemento
ocupado en el array.
Ejemplo
#define MaxElemPila
struct _TPilaEnteros {
int elementos[MaxElemPila];
int cima;
};
typedef struct _TPilaEnteros TPilaEnteros;
void CreaPila (TPilaEnteros *p) { p->cima = 0; };
int InsertaPila (int nelem, TpilaEnteros *p) {
if (p->cima==MaxElemPila) {
return 0; /*No se ha podido insertar*/
} else {
p->cima++;
p->elementos[p->cima]=nelem;
return 1;
};
};
Tema VII. TDA Colas
Definición
Las inserciones se hacen por un extremo y los borrados se hacen por el otro
extremo. Se conocen como estructuras FIFO (First In First Out).
Operaciones
Crear_cola (C: cola, ok:lógico)
Borrar_cola (C: cola, ok:lógico)
Vacía? (C: cola, resp:lógico)
Llena? (C: cola, resp:lógico)
Queue (C: cola, E: Elto, resp: lógico)
Dequeue (C: cola, E: Elto, resp: lógico)
Tamaño (C: cola, n: numérico)
Representación
Primero: indica el índice de la posición del primer elemento de la cola, es
decir, la posición el elemento a retornar cuando se invoque sacar.
Último: indica el índice de la posición de último elemento de la cola. Si se
invoca encolar, el elemento debe ser insertado en el casillero siguiente al que
indica la variable.
numElem: indica cuántos elementos posee la cola. Definiendo MAX_ELEM
como el tamaño máximo del arreglo, y por lo tanto de la cola, entonces la cola
esta vacía si numElem==0 y está llena si numElem==MAX_ELEM.
Ejemplo
class ColaArreglo {
private Object[] arreglo;
private int primero, ultimo, numElem;
private int MAX_ELEM=100; // maximo numero de elementos en la cola
public ColaArreglo() {
arreglo=new Object[MAX_ELEM];
primero=0;
ultimo=MAX_ELEM-1;
numElem=0;
}
public void encolar(Object x) {
if (numElem<MAX_ELEM) // si esta llena se produce OVERFLOW {
ultimo=(ultimo+1)%MAX_ELEM;
arreglo[ultimo]=x;
numElem++;
}
}
public Object sacar() {
if (!estaVacia()) // si esta vacia se produce UNDERFLOW {
Object x=arreglo[primero];
primero=(primero+1)%MAX_ELEM;
numElem--;
return x;
}
}
public boolean estaVacia()
{
return numElem==0;
}
}
Tema VIII. TDA Listas
Definición
Una lista es una colección homogénea de elementos con una relación lineal
entre ellos. Es decir, cada elemento de la lista (excepto el primero) tiene un
único elemento predecesor y cada elemento (excepto el último) tienen un
elemento sucesor
Operaciones
Creación: CreaLista
Transformacion: VaciarLista, InsertarElementoLista, BorrarElementoLista,
ModificarElementoLista
Observación: LongitudLista, RecuperarElementoLista
Iteradores: PrimeroLista, SiguienteLista, AnteriorLista, FinalLista
Representación
La representación escogida dependerá de la utilización que se le vaya a dar al
tipo. Lo normal es implementarlas como listas de elementos enlazados mediante
punteros.
Los elementos serán estructuras con un uno o varios campos de datos y un
campo de tipo puntero que hará referencia al siguiente elemento.
Ejemplo
/*lista de enteros*/
struct Tnodo {
int dato;
struct Tnodo *siguiente;
};
typedef struct Tnodo *TLista;
/*Permitira iterar sobre la lista*/
typedef struct Tnodo *TPosicion;
Descargar