lectura1TDA.

Anuncio
LECTURA SOBRE TDA
Observación: este apunte fue extraído de lo escrito por los siguientes autores: Josué Gala; Lorena
Bojorquez; Behrouz A. Forouzan; es esencial que lo lea para que comprenda que son los TDA´S.
A1 menos que se tengan niños pequeños (como es mi caso), los diversos objetos en casa suelen estar
acomodados de acuerdo a cierto orden, agrupados con los de su clase: los libros en un librero, la despensa en la
alacena, los alimentos perecederos en el refrigerador, la ropa en el ropero o en el “closet”, etc. En nuestros
lugares de trabajo las cosas son similares, en general los objetos de los que nos servimos suelen estar
organizados de acuerdo con un orden preestablecido. La razón para mantener las cosas en un estado por lo
menos cercano a la organización perfecta, es la eficiencia. Todos hemos padecido el disgusto, cuando no la
desesperación, de buscar algo que hemos dejado en algún lugar ajeno a su colocación habitual. Se pierden
miserablemente varias horas buscando, a veces infructuosamente, un objeto perdido en la complejidad de
nuestro entorno.
Hay casos extremos en los que la organización de los objetos es fundamental. En el caso de una biblioteca, por
ejemplo, el orden de los libros en la estantería debe ser perfecto. Pensemos en buscar un libro especifico en
una biblioteca en la que los volúmenes están acomodados aleatoriamente o siguiendo algún criterio
extravagante (por tamaño, por grosor o por lo que sugiere el titulo). ¿Cuanto tiempo tomaría encontrar un libro
en particular? No podemos saberlo, pero en el peor de los casos sería el último luego de haber recorrido todos
los títulos en el acervo, así que nos tardaremos más cuanto mayor sea este. Los libros están organizados
estrictamente para poder encontrar cualquiera de ellos rápidamente. Lo mismo ocurre con las historias médicas
en un hospital, con los archivos de una escuela, los de la compañia de teléfonos o del registro civil. A pequeña
escala también ocurre en nuestros hogares. Idealmente organizamos los CD’s, los libros, las cuentas por pagar,
las facturas, la despensa, el contenido del refrigerador y la ropa por lavar. Toda esta organización es para poder
hacer rápidamente ciertas operaciones: poner música, lavar ropa, comer o cepillarse los dientes.
Poseer cierta estructura en los objetos que manipulamos permite optimizar el tiempo invertido en las
operaciones que hacemos con ellos. En el contexto de los programas de computador la situación no es
diferente. Los programas operan con datos de entrada, los manipulan a través de una secuencia finita de pasos
y luego nos entregan resultados basados en esos datos. Nuestros programas serán más eficientes, aprovecharán
mejor los recursos disponibles (tiempo de procesador, memoria y acceso a dispositivos de E/S), dependiendo
de la manera en que son organizados los datos de entrada o los resultados parciales del proceso. Igual que en
una biblioteca, la manera de organizar los datos establece vínculos entre ellos y se conforma lo que
denominaremos una estructura de datos, uno de los temas fundamentales del presente texto.
Para poder evaluar la eficiencia de nuestros algoritmos en general, y en particular el impacto que diversas
estructuras de datos tienen sobre dicha eficiencia, requeriremos de métodos que nos permitan cuantificar los
recursos consumidos. El término adecuado para referirse es: análisis de algoritmos,(otro tema que se tratará en
el curso).
Ambas cosas tienen singular relevancia tanto en el ámbito de la computación teórica como en el de la práctica
de la programación. No puede haber una propuesta seria de un nuevo algoritmo o un protocolo de
comunicación que no esté sustentada por un análisis teórico de los mismos. Asimismo, no es posible pensar en
que las decisiones de un programador respetable no sean las adecuadas para optimizar el desempeño de sus
programas.
El análisis de algoritmos y las estructuras de datos, como el resto de los análisis que se hacen en ciencia, están
basados en abstracciones. La abstracción es el camino que los seres humanos utilizamos para comprender la
complejidad. La teoría de la gravitación, el algebra de Boole, los modelos económicos y los ecológicos son
ejemplos de ello. Todos son abstracciones hechas en un intento por comprender fenómenos complejos en los
que intervienen una multitud de factores con intrincadas relaciones entre ellos.
1
Extracto de: Estructuras de Datos y Análisis de Algoritmos, una Introducción usando Java. Josué Gala. 2005 Fac. de
Ciencias, UNAM.
Una abstracción es una descripción simplificada de un sistema y lo más importante en ella es que enfatiza las
características esenciales y descarta aquellas que se consideran sin importancia para explicar el
comportamiento del sistema. En la teoría de la gravitación, por ejemplo, no son consideradas las propiedades
magnéticas o químicas de los cuerpos, solo interesan cosas como su masa y las distancias entre ellos.
Formular una buena abstracción es como hacer una buena caricatura. El Quijote de Pablo Picasso es un buen
ejemplo de abstracción (ver figura)
Con unos cuantos trazos simples el caricaturista representa un personaje que es posible reconocer sin
ambigüedad, nada sobra y nada falta, ha sabido encontrar aquellos rasgos que caracterizan a la persona y ha
sabido resaltarlos aislándolos de todos los que no son relevantes. En la figura anterior se muestra un buen
ejemplo de abstracción. Todos podemos reconocer a Don Quijote y Sancho en sus respectivas monturas y en el
episodio de los molinos de viento, no hacen falta los colores ni las texturas ni los detalles de rostros, cuerpos y
paisaje.
TDA’S, ESTRUCTURAS DE DATOS
Por supuesto la programación de computadores es un ejercicio de abstracción. Particularmente cuando se
definen las propiedades y los atributos de los datos que deben manipular los programas. En el paradigma
actual de la programación se pretende modelar con entes abstractos llamados objetos.
Los atributos y el comportamiento de estos objetos están determinados por la abstracción que el programador
hace de los actores reales con base en el contexto del problema. Si lo que se pretende es modelar personas de
una cierta localidad con el propósito de estudiar sus características genéticas, entonces convendría considerar
como abstracción de persona un conjunto de atributos como la estatura, el color de ojos, de cabello, de piel o el
tipo sanguíneo; si el problema en cambio, está vinculado con las características socio-económicas, entonces los
atributos que convendría incluir en la abstracción son los ingresos mensuales, el gasto promedio y el tipo de
trabajo de las personas reales.
A fin de cuentas lo que hace el programador es crear un nuevo tipo de dato que modele los objetos
involucrados en el problema que pretende resolver.
Al igual que los tipos elementales que posee el lenguaje de programación que utilizará, el tipo definido por el
programador posee un conjunto de posibles valores, un dominio y un conjunto de operaciones básicas
definidas sobre los elementos de ese dominio. Un modelo así se conoce como un Tipo de Dato Abstracto.
Un tipo de dato abstracto o TDA es un modelo que describe a todos los elementos de un cierto conjunto
dominio, especificando su comportamiento bajo ciertas operaciones que trabajan sobre ellos. El uso del
término abstracto significa, como sabemos, que solo atiende a aquellas cualidades que interesan de los
elementos del dominio y que son manifiestas a través de las operaciones. Esto significa, en términos
matemáticos, que un TDA no dice más que aquello que se puede inferir del comportamiento de sus
operaciones, es lo que suele llamarse un sistema formal, cómo lo son la geometría euclidiana, la lógica de
primer orden o los números naturales. Como en todo sistema formal, el comportamiento básico de los
elementos del dominio está regido por una serie de premisas elementales que se suponen verdaderas a priori,
un conjunto de axiomas.
La cualidad más relevante en la abstracción de datos es que, al elaborar un nuevo modelo para un tipo de dato
lo importante es decidir qué es lo que se puede hacer con un dato de ese tipo y no cómo es que se hace.
La especificación de lo que se puede hacer (las operaciones) debe ser lo suficientemente rigurosa como para
explicar completamente su efecto sobre los datos que componen al tipo, pero no debe especificar cómo es que
se logra dicho efecto ni cómo estos datos están organizados. Es decir, la definición de un TDA es diferente de
su implementación concreta en un lenguaje de Programación.
Lo que se pretende decir es que un TDA está en un nivel de abstracción mayor que su realización en un
lenguaje de programación.2
**************
TIPOS DE DATOS ABSTRACTOS (TDA)
3
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 lenguaje. En pocas palabras, si los tipos de datos existentes en el lenguaje no son
suficientes o no son eficientes para ciertas aplicaciones, la mayoría de los lenguajes de programación permiten
al usuario definir sus propios tipos de datos. Esta definición consiste en establecer los elementos de que consta
el tipo así como las operaciones que se pueden realizar con instancias de este tipo.
DECLARACIÓN DE TDA’s
Para construir un tipo abstracto se debe:
1) Establecer la definición del tipo
2) Definir también las operaciones (funciones y procedimientos) que pueden operar con dicho tipo
3) Ocultar la presentación de los elementos del tipo de modo que sólo se puede trabajar con ellos usando los
procedimientos definidos en 2)
4) Poder crear instancias múltiples del tipo
Un TDA es el elemento básico de la abstracción de datos. Debe verse como una caja negra, pues la
representación y la implementación deben permanecer “ocultas”, de forma que para trabajar con los elementos
de un TDA el único mecanismo permitido es el de usar las operaciones definidas para dicho TDA.
La declaración de TDA’s en C++ requiere de palabras reservadas. Los campos, a su vez, pueden ser variables
de tipos definidos por el lenguajes u otros TDA’s.
Considere el siguiente ejemplo:
struct Tipo_Persona {
int edad;
double altura;
double peso;
char nombre[25];
};
2
Esta parte ha sido obtenida de artículo: Estructuras de Datos y Análisis de Algoritmos, una Introducción usando Java.
Josué Gala 2005 Fac. de Ciencias, UNAM.
3
Extraído de: Programación Instituto Tecnológico de Celaya, Ingeniería Química
En tal ejemplo, se esta creando una estructura de datos que definirá un nuevo tipo. Este nuevo tipo se
denomina Tipo_Persona. Observe que los elementos del nuevo tipo son cuatro; todos ellos representando
características particulares del Tipo_Persona. En general, se esperaría desarrollar “operaciones” sobre este
nuevo tipo que permitieran modificar cada uno de estos 4 campos o elementos.
Sea la siguiente sentencia:
typedef struct Tipo_Persona Persona;
Lo que esta sentencia lograría es que se está definiendo un nuevo tipo de datos llamado Persona, que contiene
exactamente la misma estructura y elementos que la estructura Tipo_Persona definida anteriormente. En otras
palabras, con las definiciones anteriores existiría un nuevo tipo en el lenguaje denominado Persona, que podrá
utilizarse como cualquier otro tipo. Por ejemplo, si se tiene:
Persona Gabriel, Antonio;
Se estarán creando dos nuevas variables, Gabriel y Antonio, del tipo Persona.
De esta forma, cada una de estas variables (Gabriel y Antonio) contiene todos los elementos definidos en la
estructura Tipo_Persona. Obsérvese aquí, que la estructura que contienen estas dos nuevas variables queda
“oculta”. Concluimos esta sección mostrando la forma en que cada uno de los elementos de una estructura de
datos puede ser accedido. Observe los siguientes ejemplos:
Gabriel.edad = 25;
Antonio.altura = 1.76;
Logrado este acceso, los elementos de estas estructuras se pueden manipular como cualquier otra variable de
su mismo tipo
OPERACIONES SOBRE UN TDA
Las operaciones que se aplican a un TDA generalmente caen dentro de las siguientes tipos básicos:
1) Construcción: Crean una nueva instancia del tipo
2) Transformación: Cambian el valor de uno o más elementos del tipo
3) Observación: Permiten determinar el valor de uno o más elementos de un tipo sin modificarlos
4) Iteradores: Permiten procesar todo los elementos de un TDA en forma secuencial
Aunque aquí no se analizarán de la creación de cada uno de estos tipos de operaciones.4
Descripción de las operaciones de un TDA5.
Cada operación relacionada con el TDA debe describirse con los siguientes puntos:
•
Nombre de la operación.
•
Descripción breve de su utilidad.
•
Datos de entrada a la operación
•
Datos que genera como salida la operación
•
Pre-condición: Condición que deberá cumplirse antes de utilizar la operación para que se realice sin
problemas
•
Post-condición: Condición en que queda el TDA después de ejecutar la operación
Ejemplo
•
Especificación Lógica del Tipo de Dato Abstracto (TDA) Cadena
•
Elementos: todos los caracteres alfabéticos (letras mayúsculas y minúsculas), caracteres numéricos y
caracteres especiales
•
Dominio: existen entre 0 y 80 caracteres en cada valor del TDA CADENA. El dominio serán todas
aquellas secuencias de caracteres que cumplan con las reglas.
4
5
Programación Instituto Tecnológico de Celaya. Ingeniería Química
Apuntes de estructura de datos; Adriana Lorena Bojorquez. Inst.Tec de Monterrey, Campus Estado de México
Operaciones
•
•
•
•
•
BORRA_INICIO
o
UTILIDAD: Sirve para eliminar el primer carácter de una cadena.
o
ENTRADA: Cadena S sobre la que se desea eliminar el primer carácter.
o
SALIDA: El carácter mas a la izquierda de la cadena S y la cadena S modificada.
o
PRECONDICIÓN: La cantidad de caracteres es mayor que cero.
o
POSTCONDICIÓN: La cadena S tiene todos los caracteres, menos el primero.
AGREGA_FINAL
o
UTILIDAD: Sirve para agregar un carácter al final de una cadena.
o
ENTRADA: Cadena S y el carácter L, que se añadirá a la cadena S.
o
SALIDA: Cadena S modificada.
o
PRECONDICIÓN: La cantidad de caracteres en S es menor que 80.
o
POSTCONDICIÓN: La cadena S tiene el carácter L que queda al extremo derecho de la cadena.
VACÍA
o
UTILIDAD: Sirve para verificar si una cadena esta vacía o no.
o
ENTRADA: Cadena S que se verificará
o
SALIDA: VERDADERO si la cadena S no tiene caracteres, FALSO en caso contrario.
o
PRECONDICIÓN: Ninguna
o
POSTCONDICIÓN: Ninguna (pues la cadena S no se modifica).
LLENA
o
UTILIDAD: Sirve para verificar si una cadena esta llena o no.
o
ENTRADA: cadena S que será verificada.
o
SALIDA: VERDADERO si la cadena S contiene ya 80 caracteres, FALSO en caso contrario.
o
PRECONDICIÓN: Ninguna
o
POSTCONDICIÓN: Ninguna (pues la cadena S no se modifica). .
INVIERTE
o
UTILIDAD: Sirve para invertir el orden de los caracteres en una cadena.
o
ENTRADA: Cadena S a la que se desea invertir el orden de los caracteres.
o
SALIDA: Cadena S modificada.
o
PRECONDICIÓN: Ninguna
o
POSTCONDICIÓN: La secuencia de caracteres en la cadena S se invierte, de forma que el primer
carácter toma el lugar del último, el segundo el del penúltimo y así sucesivamente.
Niveles de abstracción de datos
Al aplicar la abstracción de datos se pueden definir tres niveles de trabajo:
1. El nivel lógico o abstracto, que correspondería a la especificación lógica del TDA que se describió
anteriormente. En este nivel se define abstractamente la estructura de datos y las operaciones relacionadas
con ella. La descripción que se obtenga en este nivel debe ser independiente del lenguaje de programación
en el que se implementará o usará la estructura.
2. El nivel físico o de implementación. En este nivel se decide el lenguaje de programación en que se
implementará la estructura, que tipos de datos ya definidos servirán para representarla y, finalmente, bajo
estas consideraciones, se implementa como un módulo a cada una de las operaciones del TDA. Este nivel
toma el diseño que se ha realizado a nivel lógico y, siguiendo lo que indican las especificaciones de cada
operación, construye la estructura que posteriormente se usará en el nivel aplicación.
3. En el nivel aplicación o de uso el programador usará el TDA para resolver determinada aplicación. El uso
del TDA se limita a llamar las operaciones sobre la estructura que se requiera cuidando siempre de cumplir
con las reglas de cada operación especificadas en el nivel lógico.
4. Independencia de datos y el ocultamiento de información. De lo descrito en la sección anterior se observa
que hay una independencia bien marcada entre el nivel físico y el nivel de aplicación del TDA, con el nivel
lógico como intermediario. Esto significa que quien implementa el TDA no debe estar influenciado por la
aplicación que tendrá la estructura y quien use la estructura no tiene por qué saber cómo se implementaron
sus operaciones.
Entonces, se dice que la forma en que se almacenan los datos en la estructura es independiente de su aplicación
y que para el usuario permanece oculto cómo se implementaron las operaciones del TDA. Esto, sin lugar a
dudas, simplifica la labor del usuario del TDA, pues se olvida de detalles de programación al basar su trabajo
sólo en el diseño lógico del TDA. Adicionalmente, quien implementa el TDA, podrá hacer cambios o mejoras
a su implementación, respetando la especificación lógica y sin afectar en lo más mínimo las aplicaciones
desarrolladas.
Distinción entre los niveles de abstracción. Una analogía podría hacerse al comparar este proceso con el que se
realiza al construir una casa. Primero se trabaja en el nivel lógico al pedirle a un arquitecto que diseñe el plano;
el arquitecto hace una abstracción y plasma en el papel los rasgos principales de la casa por construir. Además,
especifica claramente medidas y condiciones de construcción y de uso. Una vez aprobado el diseño, se procede
en el nivel físico, que correspondería a la construcción. Los albañiles seguirán paso a paso las especificaciones
dadas en el plano (diseño en nivel lógico) y no tienen por que preguntar para qué se utilizará cada uno de los
espacios construidos. Además, utilizarán el material más apropiado para cada situación. Una vez que la
construcción esté terminada, llegará su dueño para habitarla, dándole el uso correspondiente a cada espacio
(nivel aplicación). El dueño, al utilizar la casa, no necesita saber cómo se hizo, con qué materiales o quienes la
construyeron; sin embargo, le será útil conocer algunas medidas o condiciones de construcción que se
representan en el plano (nivel lógico).
De la misma forma, cuando se desea aplicar la abstracción de datos en el desarrollo de software que requiere
de una estructura de datos, se debe comenzar con el diseño a nivel lógico del TDA, continuar con su
implementación y finalmente con su uso en el desarrollo de la aplicación correspondiente. En este proceso
podrán intervenir tres personas: el diseñador del TDA, un programador a nivel físico y un programador a nivel
aplicación. Cuando el mismo programador trabaje en los niveles físicos y de aplicación, debe tener en cuenta
la regla de no invadir los niveles, respetando el nivel lógico que es intermediario.
Ventajas al utilizar la técnica de abstracción de datos
Seguir la regla de los tres niveles de abstracción redunda en un mejor desarrollo de software. La técnica obliga
a diseñar modularmente y, como consecuencia, se tiene una implementación mas clara, documentada y es fácil
darle mantenimiento.
Adicionalmente, gracias a la independencia de datos y al ocultamiento de información, se pueden crear
paquetes como unidades de software reutilizable, con lo que se obtienen estructuras de datos genéricas.
Quien utiliza un TDA se limita a llamar las operaciones, cuidando solamente de cumplir con las
especificaciones del diseño lógico, lo que facilita y hace más rápido el desarrollo de aplicaciones, pues no es
necesario manejar los detalles físicos de la estructura.
Ejemplo: En cierta aplicación se requiere calcular el factorial de un número entero positivo. La función
factorial aplicada sobre un numero es la multiplicación de todos los números, desde el l hasta el valor del
numero correspondiente ( n! = 1 * 2 * 3 * ...* (n – l ) * n ).
Solución :
int j, factorial = 1 ;
for ( j = n; j > 0; j– – )
factorial =factorial *j;
Es importante notar que el factorial de un número crece en forma exponencial: 1! = 1, 2! = 2, 3! = 6, 4! = 24,
5! = 120, 6! = 720,7! = 5040, 8! = 40320 ........
La capacidad de los tipos de dato enteros, esta limitada. Lo cual permitirá obtener sólo hasta un factorial bien
acotado.
Por lo tanto, se requiere de un tipo de dato con una capacidad para almacenar a cualquier numero entero, sin
importar que tan grande sea;,normalmente los lenguajes no proveen de un tipo estándar para este caso; se
puede diseñar, entonces, un TDA para utilizar números enteros grandes, el cual a su vez será una estructura de
datos.
Diseño del TDA número (nivel lógico)
ESPECIFICACIÓN LÓGICA:
•
Elementos: un número se compone de dígitos.
•
Dominio: se pretende que un número pueda contener cualquier cantidad de dígitos bajo cualquier
combinación. Sin embargo, se puede limitar a una capacidad máxima de mil dígitos.
Operaciones: las mismas que posee el tipo de dato entero.
•
•
•
SUMA
o
UTILIDAD: sirve para sumar dos números.
o
ENTRADAS: dos números
o
SALIDAS: un número que guarda la suma de los dos números de entrada.
o
PRECONDICIÓN: Ninguna
o
POSTCONDICIÓN: El número de salida contiene la suma aritmética de los dos números de
entrada.
DESPLIEGA
o
UTILIDAD: Sirve para desplegar en pantalla un número.
o
ENTRADAS: Número a desplegar.6
o
SALIDAS: Ninguna (Observa en pantalla)
o
PRECONDICIÓN: Ninguna
o
POSTCONDICIÓN: Ninguna
--------
Con base en este diseño lógico, se puede pasar a la implementación del TDA (nivel físico) para posteriormente
utilizarlo (nivel de aplicación) y resolver el problema factorial eficientemente.
6
Apuntes de estructura de datos; Adriana Lorena Bojorquez. Inst.Tec de Monterrey, Campus Estado de México
Concepto grafico7
Flujos de
datos
interno
Estructuras de datos
Datos
Operación A
Operación
C
Operación B
Datos
Llamadas
interna
Interfaz
externa
El área sombreada con un entorno irregular representa el modelo. Dentro del área abstracta hay dos
aspectos del modelo : la estructura de datos y las funciones operativas: Ambas están totalmente contenidas
en el modelo y no dentro del ámbito del usuario. No, obstante, la estructura de datos está disponible para
todas las operaciones con TDA según se requiera y una operación puede llamar a otras funciones para
cumplir su tarea. Dicho de otra forma, las estructuras de datos y las funciones están dentro del ámbito de la
una y de la otra.
Los datos se introducen, se accede a ellos y se eliminan parcialmente mediante interfaces operativas
(dibujadas con rectángulos). Para el encabezado (header) de cada operación, se supone que existe un algoritmo
que realiza una operación específica. Sólo el nombre de la operación y sus parámetros están visibles para el
usuario y proporcionan la única interfaz para el TDA: Operaciones adicionales pueden crearse para cumplir
requisitos específicos.
7
Grafico obtenido de libro: Introducción a la ciencia de la computación: Autor Behrouz A. Forouzan
Descargar