4. Presentación
Javier Vélez Reyes jvelez@lsi.uned.es0 - 2
Estrategias de programación y estructuras de datos
Título de la asignatura
Código
Número de créditos
Tipo
Curso
Estrategias de programación y estructuras de datos
71901043
6 – ECTS (150 horas)
Troncal Anual
1º
Julio Gonzalo Arroyo (Coordinador)
e-mail : eped@lsi.uned.es
Lugar: ETSI Informática – UNED
Horario de tutorías: Jueves 16:00 a 20:00
José Ignacio Mayorga Toledano (profesor)
e-mail : eped@lsi.uned.es
Lugar: ETSI Informática – UNED
Horario de tutorías: Jueves 16:00 a 20:00
I. Datos de la asignatura
II. Equipo docente
Fernando López Ostenero (Profesor)
e-mail : eped@lsi.uned.es
Lugar: ETSI Informática – UNED
Horario de tutorías: Jueves 16:00 a 20:00
Tutor de Apoyo en Red
e-mail : eped@lsi.uned.es
Foros de la asignatura
5. Presentación
Javier Vélez Reyes jvelez@lsi.uned.es0 - 3
III. Atención al alumno
› Entorno virtual
- http://virtual.uned.es
- Material didáctico
- Foros de atención al alumno
› Página oficial de la asignatura
- hOp://www.lsi.uned.es/eped
- Transparencias
- Consulta de notas
› Equipo docente en sede central
- Por correo
- Por teléfono
- Presencialmente en horario de guardias
Estrategias de programación y estructuras de datos
6. Presentación
Javier Vélez Reyes jvelez@lsi.uned.es0 - 4
Estrategias de programación y estructuras de datos
IV. Obje8vos generales de la asignatura
› Obtener un conocimiento de los principales tipos de datos
› Adquirir la capacidad de usar esos tipos en contextos realistas de aplicación
› Aprender algoritmos típicamente aplicados sobre estos tipos de datos
› Adquirir soltura en la aplicación de estrategias algorítmicas de carácter recursivo
› Adquirir soltura en la aplicación de estrategias algorítmicas de carácter iterativo
› Obtener capacidad para analizar y comparar la eficiencia de los algoritmos
› Aprender a diseñar, formalizar e implementar los tipos de datos
› Adquirir una actitud crítica del uso de tipos de datos en la orientación a objetos
7. Presentación
Javier Vélez Reyes jvelez@lsi.uned.es0 - 5
Estrategias de programación y estructuras de datos
V. Contenidos de la asignatura
Parte I. Introducción
1. Las Estructuras de datos desde la OOP
2. Estrategias de programación
3. Análisis de la eficiencia de algoritmos
4. Tipos Abstractos de Datos
Parte II. Tipos lineales de datos
5. Listas
6. Pilas
7. Colas
Parte III. Tipos jerárquicas de datos
8. Árboles generales
9. Árboles binarios
10. Árboles binarios de búsqueda
8. Presentación
Javier Vélez Reyes jvelez@lsi.uned.es0 - 6
Estrategias de programación y estructuras de datos
VI. Trabajo a realizar
› 1 prueba presencial
› Preguntas de teoría
› Ejercicios prácticos
› Práctica
› Carácter individual y obligatorio
› Diseño e implementación de un problema de tipos de datos orientados a objetos
› 1 sesión de control en el Centro Asociado de asistencia obligatoria
22
VII. Normas de evaluación
0.8 NE + 0.2 NP >= 5.0
› 2 convocatorias anuales (Junio y septiembre)
› Notas
› NE = Nota Examen
› NP = Nota Práctica
10. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 2
Índice
Índice
› Introducción
› Programación orientada a objetos
› ¿Qué es la programación orientada a objetos?
› Mecanismos de la programación orientada a objetos
› Fundamentos de la programación orientada a objetos
› Anatomía de Clases
› Bibliografía
11. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 3
Obje6vos generales
Obje8vos
› Obtener una visión histórica de la evolución de la programación
› Entender el papel que juega la orientación a objetos dentro de la programación
› Entender las principales características de la programación estructurada
› Entender las principales características de la programación orientada a objetos
› Apreciar los factores diferenciales entre ambos paradigmas
› Adquirir habilidades de análisis acerca de cuándo conviene usar uno y otro
› Valorar las capacidades de la orientación a objetos en el marco de los TADS
› Valorar el avance conceptual que supone trabajar con TADS dentro de objetos
› Obtener una actitud critica para valorar el uso y diseño de en OOP
12. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 4
Introducción
Introducción
Programación
estructurada
Programación
orientada a objetos
Tipos abstractos
de datos
I. Programación estructurada
El paradigma de programación estructurada centra la construcción de
so@ware en la creación de abstracciones funcionales organizadas de
forma composi6va de acuerdo a una estructura jerárquica
El programa principal se descompone
funcionalmente en subproblemas que
a su vez se descomponen funcionales
en abstracciones más sencillas hasta
llegar a operaciones atómicas
El problema de esta aproximación es
que se asume, irrealistamente, que la
especificación del problema no cambia
a lo largo del tiempo de desarrollo del
proyecto. Además la reutilización de
cada descomposición está confinada
al contexto funcional donde aparece
implicado
}Garaje
Diagnos6co Reparación
Eléctrica Mecánica
Vehículo
13. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 5
Introducción
Introducción
Programación
estructurada
Programación
orientada a objetos
Tipos abstractos
de datos
II. Tipos abstractos de datos
Con el ánimo de fomentar la reu6lización de código se buscan
artefactos más estables dentro de la evolución del desarrollo de los
productos de so@ware. Las abstracciones de datos, que organizan
datos de acuerdo a determinada lógica estructural son los candidatos
idóneos
Vehículo
}Garaje
Diagnos6co Reparación
Eléctrica Mecánica
usa
Si bien el proceso de
construcción de software
sigue estando basado en
abstracciones funcionales,
ahora se realizan abstrac-
c i o n e s d e d a t o s q u e
representan entidades del
dominio del problema que se
van transformando a lo largo
del árbol de descomposición
14. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 6
Introducción
Introducción
Programación
estructurada
Programación
orientada a objetos
Tipos abstractos
de datos
III. Programación orientada a objetos
El programación orientada a objetos proporciona los mecanismos
necesarios de los que adolece el paradigma estructurado para
ar6cular soluciones completamente centradas en abstracciones de
datos
Vehículo
+ arrancar ()
+ parar ()
Garaje
+ Reparar (Vehículo v)
usa
}
Ahora toda la arquitectura software de la solución se articula
en términos de un ecosistema de abstracciones de datos
(objetos) que colaboran entre si por medio del envío de
mensajes (invocaciones de operaciones)
La ventaja de esta aproximación es que permite central
preliminarmente el desarrollo en la construcción de las
abstracciones y postergar el cuerpo funcional para las últimas
fases del proyecto, que se expresa como un algoritmo
distribuido entre objetos
15. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 7
Programación orientada a objetos
¿Qué es la programación orientada a objetos?
La construcción de so@ware orientado a objetos es el método de desarrollo so@ware que
basa la arquitectura de un sistema so@ware en artefactos deducidos de los 6pos de objetos
que éste manipula en lugar de basarse en la función o funciones a las cuales el sistema
debe responder
Programación
estructurada
Programación
orientada a objetos
Descomposición
funcional descendente
Ecosistema de
colaboración entre objetos
A
B C
D E
a : A b : B
c : C
Desarrollo
centrado en
abstracciones
funcionales
Desarrollo
centrado en
abstracciones de
datos
– Nivel de reutilización +
16. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 8
Programación orientada a objetos
Mecanismos básicos de la programación orientada a objetos
El paradigma de programación orientada a objetos se ar6cula, esencialmente, a través de
cuatro mecanismos fundamentales: Clases, métodos, objetos y mensajes. De ellos los dos
primeros 6enen lugar en fase de diseño, mientras que los segundos corresponden a la fase
de ejecución
I. Clases
Una clase es una especificación formal y computable que se
u6liza para construir objetos de un mismo 6po en fase de
ejecución. Internamente está descrita en términos de una
colección de atributos y una serie de operaciones
Fase de diseño
Coche
- marca
- modelo II. Métodos
La colección de métodos de una clase define las capacidades
de la misma y conforma un contrato programá6co (API) para
acceder o alterar los atributos de la misma. Los métodos
ocultan su implementación a resto de clases de manera que
éstas se perciben unas a otras como artefactos con
capacidades de sencilla invocación
+ getMarca ()
+ getModelo ()
clase
métodos
atributos
17. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 9
Programación orientada a objetos
Mecanismos básicos de la programación orientada a objetos
El paradigma de programación orientada a objetos se ar6cula, esencialmente, a través de
cuatro mecanismos fundamentales: Clases, métodos, objetos y mensajes. De ellos los dos
primeros 6enen lugar en fase de diseño, mientras que los segundos corresponden a la fase
de ejecución
III. Objetos
Un objeto es un ejemplar de una clase que reside en memoria
durante cierto 6empo en la fase de ejecución. Está formado
por un estado definido a par6r del valor que toma en cada
momento cada atributo de la clase en ese ejemplar
Fase de ejecución
IV. Mensajes
El acto de invocación de un métodos sobre un objeto en
6empo de ejecución se refiere como envío de mensaje. En
orientación a objetos los algoritmos son colaboración entre
objetos expresadas en términos de mensajes que fluyen de
unos a otros. Cada mensaje 6ene como efecto ejecutar el
algoritmo del método descrito en la clase
miCoche : Coche
- ‘Renault’
- ‘Clio’
objeto
estado
Cliente
miCoche.getMarca ()
‘Renault’
mensaje
respuesta
18. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 10
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
I. Abstracción
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
La abstracción es el proceso mediante el cual describimos una realidad del dominio del
problema para crear una representación simplificada dentro del dominio de solución.
Esta simplificación se basa en la supresión, conversión o adaptación de caracterís6cas
reales en atributos sistémicos y se llama abstracción de datos
Motor
- combustible
- nCilindros
- fabricante
- modelo
Dominio de la solución Dominio del problema
abstracción
19. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 11
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
II. Encapsulación
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
La encapsulación es el proceso por el cual la colección de
métodos de una clase protege el acceso ilegal al estado de un
objeto por parte de otros objetos según la lógica de negocio. De
esta forma los atributos no son directamente alterables sino sólo
a través de los métodos de la clase
Coche
- presión
- ...
+ getPresión ()
+ setPresión (p)
Mecánico
setPresión (6)
Según los requisitos, una presión
de 6 es excesiva, por lo tanto la
implementación del método de la
clase provoca que el mensaje no
cause ningún efecto
estado
métodos
20. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 12
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
II. Encapsulación
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
Al ar6cular la encapsulación es posible definir diferentes modificadores de acceso a los
elementos de una clase (atributos y métodos). Estos modificadores alteran las reglas de
visibilidad de los elementos desde el exterior de la clase
Modificadores
de visibilidad
de Java
Modificador private
Modificador public
Modificador protected
Un elemento definido como privado sólo es
accesible desde dentro de la clase donde se ha
declarado el elemento
Un elemento definido como público sólo es
accesible por todos los objetos del sistema
Un elemento protegido es accesible por la
propia clase y por cualquier clase hija de está
así como cualquier clase perteneciente al
paquete donde ésta está definida
Coche
- Marca
- Modelo
+ getMarca ()
+ getModelo ()
# isPlanRenove ()
21. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 13
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
III. Herencia
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
La herencia es un mecanismo que permite organizar
un conjunto de clases de acuerdo a una jerarquía. La
relación que se establece entre ellas es interpretada
como una especialización / generalización y se lee de
la forma A es un B. Mediante la herencia, se pueden
compar6r datos y métodos miembro entre clases y
subclases. Una clase hija obtendrá acceso a todos los
atributos públicos o protegidos declarados en sus
clases antecesoras. Asimismo, adquirirá la
implementación de los métodos miembro públicos o
protegidos en ellas declarados. Por su parte, las clases
hijas pueden especializar la funcionalidad de los
métodos heredados del padre por medio de la
sobrescrita de su implementación.
+ arrancar ()
+ parar ()
Vehículo
Moto
+ arrancar ()
+ parar ()
+ arrancar ()
+ parar ()
Camión
- capacidad
# nRuedas
+ arrancar ()
+ parar ()
+ llenar ()
+ vaciar ()
Coche
22. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 14
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
III. Herencia
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
La herencia permite diferir la implementación de los
métodos a alguna de las clases hijas para que hagan
una implementación especializada. En este sen6do
podemos hablar de:
A. Métodos abstractos
Un método del que se quiere diferir la
implementación debe declarase como
abstracto. Esto permite encontrar diferentes
implementaciones en cada clase
B. Clase abstracta
Un clase con métodos abstractos debe
declararse abstracta y no es directamente
instanciable
+ arrancar ()
+ parar ()
Vehículo
Moto
+ arrancar ()
+ parar ()
+ arrancar ()
+ parar ()
Camión
- capacidad
# nRuedas
+ arrancar ()
+ parar ()
+ llenar ()
+ vaciar ()
Coche
23. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 15
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
III. Herencia
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
Las jerarquías de herencia prescriben ciertas restricciones con respecto a la forma de
aplicar la lógica de construcción de los objetos. El programador puede alterar esta lógica
mediante el uso de los constructores implícitos this y super.
A. Construcción delegada
En la instanciación de objetos, antes de
ejecutar la lógica de creación del constructor
invocado, se llama al constructor sin
argumentos (u). El uso del constructor
implícito this como primera instrucción de la
lógica de creación permite alterar este
comportamiento forzando a que se u6lice otro
constructor sobrecargado con ciertos
parámetros de construcción actuales (v)
Vehículo
+ Coche ()
+ Coche (String marca)
+ Coche (int ruedas)
+ Vehiculo ()
Coche
Coche (4)
Coche (‘Renault’)
Coche ()
this (‘renault’);
this.nRuedas = ruedas;
...
v
u
v
24. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 16
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
III. Herencia
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
Las jerarquías de herencia prescriben ciertas restricciones con respecto a la forma de
aplicar la lógica de construcción de los objetos. El programador puede alterar esta lógica
mediante el uso de los constructores implícitos this y super.
B. Construcción ascendente en cascada
En la instanciación de objetos, antes de
ejecutar la lógica de creación del constructor
invocado, se llama al constructor sin
argumentos de la clase padre (u). El uso del
constructor implícito super como primera
instrucción de la lógica de creación permite
alterar este comportamiento forzando a que se
u6lice otro constructor sobrecargado en el
padre con ciertos parámetros de construcción
actuales (v)
Vehículo
+ Coche ()
+ Coche (int ruedas)
Coche
+ Vehiculo ()
+ Vehiculo (int ruedas)
Coche (4)
Coche () v
u
Vehiculo (4)
Vehiculo ()
super (4);
this.marca = ‘Renault’;
...
v
25. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 17
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
IV. Polimorfismo
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
La herencia confiere a las instancias de una clase múl6ples 6pos. En concreto, los objetos
adquirirán el 6po de la clase a la que pertenecen y el 6po definido por cada una de las
clases padre de las que heredan su comportamiento. A esta propiedad se la llama
polimorfismo
Vehículo
+ arrancar ()
+ parar ()
Moto
+ arrancar ()
+ parar ()
+ arrancar ()
+ parar ()
Camión
+ arrancar ()
+ parar ()
+ llenar ()
Coche
Tipo Camión
Los objetos de la clase Camión
adquieren el tipo Camión lo que
significa que en cualquier colaboración
de objetos, los ejemplares de esta
clase pueden utilizarse en variables
declaradas con el tipo Camión
Tipo Vehículo
Los objetos de las clases Camión – también los de la clase
Moto o Coche – adquieren además por herencia el tipo
Vehiculo, lo que permite que aparezcan en colaboraciones
de objetos con variables tipificadas con el tipo vehículo
26. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 18
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
IV. Polimorfismo
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
Las propiedades polimórficas también se confieren a través del uso de interfaces. De esta
manera, adicionalmente a lo anterior, los objetos de una clase también adquirirán el 6po
de cada una de las interfaces que implementen
Moto
+ arrancar ()
+ parar ()
+ arrancar ()
+ parar ()
Camión
+ arrancar ()
+ parar ()
+ llenar ()
Coche
Tipo Camión
Los objetos de la clase Camión
adquieren el tipo Camión lo que
significa que en cualquier colaboración
de objetos, los ejemplares de esta
clase pueden utilizarse en variables
declaradas con el tipo Camión
Interfaz
Los objetos de las clases Camión – también los de la clase
Moto o Coche – adquieren además por implementación de
la interfaz el tipo Vehiculo, lo que permite que aparezcan en
colaboraciones de objetos con variables tipificadas con el
tipo vehículo
Vehículo
+ arrancar ()
+ parar ()
Una interfaz es un artefacto
especial, similar a una clase, que
prescribe un contrato programático
estableciendo una colección de
signaturas de métodos pero no la
implementación de los mismos.
Tipo Vehículo
27. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 19
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
IV. Polimorfismo
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
Cada 6po dentro de una estructura polimórfica de herencia iden6fica un nivel de
abstracción sobre el que se puede trabajar con los objetos de la herencia. Es posible
conver6r un objeto de un 6po a otro mediante upcas6ngs y downcas6ngs
Vehículo
+ arrancar ()
+ parar ()
Moto
+ arrancar ()
+ parar ()
+ arrancar ()
+ parar ()
Camión
+ arrancar ()
+ parar ()
+ llenar ()
Coche
Tipo Camión
Los objetos Camión son una especialización de
Vehículo que disponen de ciertos métodos
propios de la abstracción Camión
Tipo Vehículo
Un objeto Camión tipificado como un Vehículo
no puede invocar métodos del tipo camión
downcast
Vehículo v = ...
Coche c = (Coche) v;
upcast
Coche c = new Coche ();
Vehículo v = (Vehículo) c;
28. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 20
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
IV. Polimorfismo
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
El polimorfismo permite ar6cular un modelo de diseño so@ware conocido por el nombre
de programación genérica, según el cual la algoritmia se describe al nivel de abstracción
de la clase padre para no vincularse a la realización prescita por ninguna de sus hijas
Vehículo
+ lavar ()
TunelDeLavado
+ lavar (Vehículo v)
Moto
+ lavar () + lavar ()
Camión
+ lavar ()
Coche
return ‘Lavando moto...’
return ‘Lavando coche...’
return ‘Lavando camión...’
v.lavar ()
Empleado
lavar (unCoche)
Lavando coche...
lavar (unaMoto)
Lavando moto...
lavar (unCamión)
Lavando camión...
29. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 21
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
V. Ligadura dinámica
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
La ligadura dinámica es la capacidad de algunos lenguajes orientados a objetos de cambiar
en 6empo de ejecución el objeto referenciado por una variable por otro objeto de dis6nto
6po polimórficamente compa6ble
cola.añadir (v)
ColaDeVehiculos
+ encolar (Vehiculo v)
+ lavarTodos ()
+ boolean hayMas ()
+ Vehiculo siguiente ()
- cola
Garaje garaje = new Garaje ()
Vehiculo v;
while (cola.hayMas ()) {
v = cola.siguiente ();
garaje.reparar (v);
}
usa Garaje
+ reparar (Vehículo v)
30. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 22
Programación orientada a objetos
Fundamentos de la programación orientada a objetos
VI. Genericidad
Lo que convierte a la programación orientada a objetos en el paradigma idóneo para
realizar diseño de sistemas centrados en abstracciones de datos es el uso de 6
caracterís6cas fundamentales: abstracción, encapsulación, herencia, polimorfismo, ligadura
dinámica y genericidad
La genericidad permite abstraerse de las los 6pos de objetos con los que trabaja
internamente una clase por medio de la parametrización de los mismos. De hecho esta
caracterís6cas es también conocida como parametrización de 6pos
PilaDeCoches
PilaDeMotos
Genericidad
Pila <T>
+ apilar (T t)
+ T desapilar ()
- Moto pila []
- Coche pila []
+ apilar (Coche p)
+ Coche desapilar ()
+ apilar (Moto m)
+ Moto desapilar ()
- T pila []
31. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 23
Tipos abstractos de datos
Anatomía de Clases
Tipos de operaciones
Cualquier clase, dentro de la programación orienta a objetos, está formada por el perfil de
cada una de las operaciones públicas que lo cons6tuyen. Éste indica la forma en que se
pueden explotar las capacidades del 6po. Desde un punto de vista conceptual es posible
dis6nguir entre varios 6pos dis6ntos de operaciones
Una operación constructora con6ene la lógica de inicialización de
un 6po de datos. Como tal, es invocada inicialmente para crear un
nuevo ejemplar vacío del 6po. Su invocación puede requerir el
paso de parámetros necesarios para la inicialización
I. Operaciones constructoras
Una operación constructora por copia realiza un proceso de
inicialización similar al anterior. La diferencia estriba en que en
esta ocasión la operación recibe como parámetro un ejemplar del
mismo 6po de datos y copia sus elementos al nuevo ejemplar
construido
II. Operaciones constructoras por copia
Stack <T>
+ Stack (int capacity)
...
Stack <T>
+ Stack (Stack s)
...
32. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 24
Tipos abstractos de datos
Las operaciones modificadoras se u6lizan para alterar de forma
segura el estado interno de una abstracción de datos. Si la
invocación es semán6camente valida garan6zan que, tras su
ejecución dejan al 6po abstracto en un nuevo estado consistente
III. Operaciones modificadoras
Las operaciones consultoras de una abstracción de datos son
aquellas que sirven para consultar de forma segura el estado
interno de la misma. Su invocación 6ene la propiedad de no
producir efectos en el estado por lo que se consideran
idempotentes
IV. Operaciones consultoras
Tipos de operaciones
Anatomía de Clases
Stack <T>
+ void push (T element)
+ void pop ()
...
Stack <T>
+ T peek ()
...
Cualquier clase, dentro de la programación orienta a objetos, está formada por el perfil de
cada una de las operaciones públicas que lo cons6tuyen. Éste indica la forma en que se
pueden explotar las capacidades del 6po. Desde un punto de vista conceptual es posible
dis6nguir entre varios 6pos dis6ntos de operaciones
33. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 25
Tipos abstractos de datos
Un 6po de operaciones consultoras son los predicados lógicos que
sirven para realizar comprobaciones seguras sobre el estado en
que se encuentra la abstracción de datos con respecto a cierta
propiedad caracterís6ca de la misma
V. Operaciones consultoras lógicas o predicados
Las operaciones comparadoras son un 6po de predicados
dedicados a comparar el estado interno de un ejemplar de la
abstracción de datos con el de otro u otros ejemplares. El caso
más recurrente es el de operaciones de igualdad entre ejemplares
del mismo 6po
VI. Operaciones comparadoras
Tipos de operaciones
Anatomía de Clases
Stack <T>
+ boolean contains (T e)
+ boolean isEmpty ()
+ boolean isFull ()
...
Stack <T>
+ boolean equals (Stack s)
+ boolean containsAll (Stack s)
...
Cualquier clase, dentro de la programación orienta a objetos, está formada por el perfil de
cada una de las operaciones públicas que lo cons6tuyen. Éste indica la forma en que se
pueden explotar las capacidades del 6po. Desde un punto de vista conceptual es posible
dis6nguir entre varios 6pos dis6ntos de operaciones
34. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 26
Tipos abstractos de datos
Las operaciones de hashing ofrecen una representación numérica
que representa de manera – casi – univoca el estado interno de
una abstracción de datos. Se u6lizan para controlar la ausencia de
elementos repe6dos en otras abstracciones agregadoras
VII. Operaciones de hashing
Las operaciones transformadoras permiten crear ejemplares de
otros 6pos de abstracciones cuyo estado interno proviene del
estado de la abstracción original, de acuerdo a cierta lógica de
transformación
VIII. Operaciones transformadoras
Tipos de operaciones
Anatomía de Clases
Stack <T>
+ long hashcode ()
...
Stack <T>
+ String toString ()
+ String toXML ()
+ List toList ()
+ Set toSet ()
...
Cualquier clase, dentro de la programación orienta a objetos, está formada por el perfil de
cada una de las operaciones públicas que lo cons6tuyen. Éste indica la forma en que se
pueden explotar las capacidades del 6po. Desde un punto de vista conceptual es posible
dis6nguir entre varios 6pos dis6ntos de operaciones
35. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 27
Tipos abstractos de datos
Las operaciones destructoras con6enen toda la lógica asociada a
la liberación de recursos que es necesario invocar cuando un
determinado ejemplar de una abstracción de datos no va a volver
a ser u6lizado a lo largo del programa
IX. Operaciones destructoras
Las operaciones reinicialidoras son un caso par6cular de
operaciones modificadoras que restablecen el estado interno de
la abstracción al original, aquel en que se encontraban cuando
fueron construidas. Su lógica interna es similar a la de una
constructora a excepción que estas operaciones no realizan
reserva de nuevos recursos
X. Operaciones reinicializadoras
Tipos de operaciones
Anatomía de Clases
Stack <T>
+ void dispose ()
...
Stack <T>
+ void clear ()
+ void removeAll ()
...
Cualquier clase, dentro de la programación orienta a objetos, está formada por el perfil de
cada una de las operaciones públicas que lo cons6tuyen. Éste indica la forma en que se
pueden explotar las capacidades del 6po. Desde un punto de vista conceptual es posible
dis6nguir entre varios 6pos dis6ntos de operaciones
36. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 28
Tipos abstractos de datos
XI. Operaciones descriptoras
Tipos de operaciones
Anatomía de Clases
Cualquier clase, dentro de la programación orienta a objetos, está formada por el perfil de
cada una de las operaciones públicas que lo cons6tuyen. Éste indica la forma en que se
pueden explotar las capacidades del 6po. Desde un punto de vista conceptual es posible
dis6nguir entre varios 6pos dis6ntos de operaciones
La implementación completa de un 6po en
no termina con la implementación de cada
una de las operaciones del mismo sino que
debe incluir 3 operaciones canónicas para
su clasificación, comparación y trazado.
Estas operaciones en java son canónicas ya
que heredan de la clase raíz (Object) y se
trata de hashcode () , equals () y toString ()
Stack <T>
hashcode () {
return 67 * elements.hashcode () +
capacity;
}
boolean equals (Object o) {
if (!(o instanceof Stack)) return false;
else {
s = (Stack) o;
return s.elements.equals (elements) &&
s.capacity == capacity;
}
String toString () {
return elements.toString ();
}
- List elements
- int capacity
37. Introducción
Javier Vélez Reyes jvelez@lsi.uned.es1 - 29
Bibliogra_a
BibliograTa
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
Bibliografía complementaria
Construcción de software orientado a objetos.
Meyer, B. Prentice Hall España. 1998. ISBN
978-84-8322-040-5
39. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 2
Índice
Índice
› Introducción
› Diseño de algoritmos recursivos
› ¿Qué son los algoritmos recursivos?
› Diseño de algoritmos recursivos
› Ejemplos de algoritmos recursivos
› Diseño de algoritmos iterativos
› ¿Qué son los algoritmos iterativos?
› Diseño de algoritmos iterativos
› Ejemplos de algoritmos iterativos
› Traducción de algoritmos recursivos a iterativos
› Catálogo de algoritmos
› Bibliografía
40. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 3
Obje6vos generales
Obje8vos
› Entender las principales características del diseño recursivo
› Entender las ventajas y desventajas del diseño recursivo
› Aprender a diseñar algoritmos recursivos
› Advertir su importancia en el contexto de las abstracciones de datos
› Entender las principales características del diseño iterativo
› Entender las ventajas y desventajas del diseño iterativo
› Aprender a diseñar algoritmos iterativos
› Advertir su importancia en el contexto de las abstracciones de datos
› Aprender a transformar algoritmos recursivos en iterativos
41. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 4
Introducción
Introducción
Todo algoritmo pretende la realización de algún 6po de tarea o cálculo. Las más de las
veces, si dicha tarea no es trivial, esto implica repe6r un conjunto de pasos sencillos un
cierto número de veces hasta que se cumpla cierta condición, que se conoce como
condición de terminación. Esencialmente, hay dos formas de diseñar algoritmos que
desarrollen tareas repe66vas, que veremos en este tema ya que representan estrategias
diferentes para resolver el mismo problema: la recursividad y la iteración
Estrategias de
programación
I. Diseño recursivo de algoritmos
El problema se resuelve por el diseño de funciones que recurren sobre si
mismas de forma directa o indirecta. Su construcción se basa en la elección
de una familia de casos base, triviales de resolver y una colección de casos
recursivos que converjan hacia los casos base y que en suma den cobertura
a todo el espectro de posibles parámetros de entrada
II. Diseño iterativo de algoritmos
El problema se resuelve por aplicación de sentencias de control de flujo de
programa sobre estructuras de datos que representan la entrada o salida
del mismo. En este caso la llamada a otra funciones dentro de una función
se debe a criterios de descomposición modular y no se aplica recursividad
para resolver el problema
42. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 5
Introducción
Introducción
int factorial (int n) {
if (n == 0) return 1;
else return n * factorial (n – 1);
}
I. Diseño recursivo
Los algoritmos de diseño recursivo permiten resolver un problema
invocando dentro del cuerpo de una función – directa o
indirectamente – nuevamente a la propia función sobre un conjunto
de parámetros actuales diferentes. Un diseño adecuado de este 6po
de algoritmos debe garan6zar que la ejecución de la función con unos
parámetros adecuados converja a la solución de manera que se
garan6ce la finalización del mismo
}
Para resolver la función
factorial se vuelve a
invocar a la función
factorial con valor n – 1 y
se devuelve el resultado de
multiplicar el valor devuelto
de esta invocación por n
Factorial (5) = 5 * factorial (4)
= 5 * 4 * factorial (3)
= 5 * 4 * 3 factorial (2)
= 5 * 4 * 3 * 2 * factorial (1)
= 5 * 4 * 3 * 2 * 1 * factorial (0)
= 5 * 4 * 3 * 2 * 1 * 1
= 120
Diseño iterativo
Diseño recursivo
43. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 6
Introducción
Introducción
I. Diseño iterativo
Los algoritmos itera6vos son aquellos que se construyen a par6r de
una secuencia ordenada de instrucciones de alto nivel. Un
subconjunto de estas instrucciones permiten alterar el flujo de
ejecución. En concreto se dis6nguen instrucciones de control de flujo
condicional – que seleccionan un camino de ejecución de entre varios
posibles – e itera6vo – que repiten la ejecución de un bloque de
instrucción mientras se sa6sfagan ciertas condiciones ambientales. Un
diseño adecuado de este 6po de algoritmos debe garan6zar la
terminación del mismo
int factorial (int n) {
int index = 1;
int result = 1;
while (index <= n) {
result = result * index;
index ++;
}
}
}
Para resolver la función factorial
se procede iterativamente
acumulando en la variable result
el producto del contador index de
cada iteración por el resultado
acumulado anterior
Factorial (5)
index 1 2 3 4 5
result 1 2 6 24 120
Diseño iterativo
Diseño recursivo
44. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 7
Diseño de algoritmos recursivos
¿Qué son los algoritmos recursivos?
El diseño
requiere la
definición de
una colección
de casos que
den cobertura a
toda entrada
legí6ma de
parámetros
Esquema general de un algoritmo recursivo
Tr función (Tx x) {
if (esCasoBase1 (x)) return <<resolución inmediata 1>>
...
if (esCasoBaseN (x)) return <<resolución inmediata N>>
if (esCasoRecursivo1 (x)) return <<resolución recursiva convergente 1>>
...
if (esCasoRecursivoM (x)) return <<resolución recursiva convergente M>>
}
Función recursiva
Casos
Guarda
La guarda del caso refleja las condiciones
ambientales que deben sa6sfacerse para
ejecutar el caso. Están expresadas en términos
de los parámetros y deben ser disjuntas entre sí
Resolución
La resolución de un caso indica las acciones que deben
efectuarse para resolver el caso. Si es base la resolución
es inmediata si es recursiva consiste en la aplicación de
una composición de llamadas recursivas
Casos base
Casos recursivos
Un algoritmo recursivo es aquel que se invoca a si mismo dentro de su propio cuerpo con
unos parámetros actuales dis6ntos. Estructuralmente cada función está formada por una
colección de alterna6vas disjuntas llamadas casos con guardas expresadas en términos de
los parámetros del problema. Los casos base resuelven el problema de forma inmediata
mientras que los otros recurren composi6vamente sobre la función
45. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 8
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Diseño de casos base
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
Un caso base representa el final de una tarea, ya que no requiere de nuevas llamadas
recursivas para su resolución debido a su sencillez. Cuando diseñamos los casos base de
un algoritmo recursivo debemos asegurarnos de que las guardas de todos ellos son
disjuntas entre sí y de que en suma dan cobertura a todas las posibles invocaciones
provenientes de algún caso recursivo
int factorial (int n) {
if (n == 0) return 1;
else return n * factorial (n – 1);
}
Toda invocación recursiva termina
por aplicación del único caso base
con guarda n==0. A veces es
posible balancear los casos de un
diseño recursivo entre los base y
los propiamente recursivos sin
impacto en la solución. Considere
que otra solución hubiera sido
definir el caso base con la guarda
n<2
Caso base
46. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 9
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Diseño de casos recursivos
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
Un caso recursivo consta de tres elementos: una división del problema en uno o más
subproblemas, una invocaciones recursiva para resolver cada uno de estos subproblemas
y una combinación de los resultados de los subproblemas para obtener, a la vuelta de las
invocaciones recursivas, el resultado del problema original. Este esquema termina si la
división del problema converge hacia alguno de los casos base de la función
int factorial (int n) {
if (n == 0) return 1;
else return n * factorial (n – 1);
}
Aquí el único caso recursivo es
aquel con guarda implícita n>0. Su
resolución consiste en una división
convergente hacia n==0 debido a
la expresión de división del
problema
Caso recursivo
División
La función de división
genera a cada paso de
recursión un subproblema
de tamaño una unidad
menor que converge a 0
Recursión
La recursión se aplica para
resolver el subproblema de
tamaño n-1
Combinación
La función de combinación en este caso
que permite resolver el problema a par6r
de los resultados parciales de cada
subproblema es la operación producto
47. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 10
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Diseño de casos recursivos
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
Un caso recursivo consta de tres elementos: una división del problema en uno o más
subproblemas, una invocaciones recursiva para resolver cada uno de ellos y una
combinación de los resultados de los subproblemas para obtener, a la vuelta de las
invocaciones recursivas, el resultado del problema original.
Clasificaciones
de recursividad
I. Por la forma de recursión
II. Por la forma de partición
III. Por la forma de combinación
El número de invocaciones realizadas
en cada caso recursivo marca un
criterio de clasificación
La forma de dividir el problema en
subproblemas es otro criterio de
clasificación
La forma de combinar los resultados
parciales de la resolución de cada
subproblema es el tercer criterio
Recursividad simple
Recursividad múltiple
Partición por substracción
Partición por división
Recursividad final
Recursividad no final
return n * f (n-1)
return f (n-1) + … + f (n-k)
return n * f (n-1)
return f (n/2)
return f (n/2)
return n * f (n-1)
48. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 11
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Diseño de recursividad por inmersión
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
A veces el diseño de una función recursiva se expresa como una invocación concreta de
una función más general que incluye parámetros adicionales. Esta técnica, conocida por
el nombre de diseño por inmersión, se aplica por dis6ntas cues6ones que discu6remos a
con6nuación
La inmersión es una estrategia de diseño mediante la cual
una función se expresa como una invocación particular de
otra función más general con parámetros adiciones
int sumaTodos (int v[]) {
return sumaDesde (v, 0);
}
int sumaDesde (int v[], int index) { ... }
Función inmersora
La función inmersora
sumerge a la original puesto
que, al ser más general, con
una invocación par6cular de
ésta se da cobertura al
problema
Función sumergida
La función sumergida
se expresa como una
invocación concreta de
la función inmersora
más general
49. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 12
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Diseño de recursividad por inmersión
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
A veces el diseño de una función recursiva se expresa como una invocación concreta de
una función más general que incluye parámetros adicionales. Esta técnica, conocida por
el nombre de diseño por inmersión, se aplica por dis6ntas cues6ones que discu6remos a
con6nuación
Táctica de
inmersión
I. Inmersión de parámetros
II. Inmersión de resultados
La inmersión de parámetros se refiere a la
aplicación de la técnica de inmersión sobre
los parámetros de entrada de la misma.
Existen 2 6pos dentro de esta categoría
La inmersión de resultados consiste en la
aplicación de la técnica de la inmersión para
acumular en parámetros el resultado del
problema en llamada recursiva
I.I. Parámetros de recorrido
Se incluyen parámetros en la función de
inmersora que controlan el recorrido de los
elementos de una estructura de datos
I.II. Parámetros acumuladores
Se incluyen parámetros en la función de
inmersora que acumulan resultados inter-
medios
50. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 13
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Diseño de recursividad por inmersión
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
A veces el diseño de una función recursiva se expresa como una invocación concreta de
una función más general que incluye parámetros adicionales. Esta técnica, conocida por
el nombre de diseño por inmersión, se aplica por dis6ntas cues6ones que discu6remos a
con6nuación
Objetivos de
inmersión
I. Inmersión por diseño
III. Inmersión por recursión final
Se aplican técnicas de inmersión con el objeto de definir
una recursión que de otro modo no sería posible ar6cular
Se aplican técnicas de inmersión con el fin de conseguir
una ejecución más eficiente de la función en la resolución
del problema
Se aplican técnicas de inmersión con el ánimo de
transformar la recursividad en recursión final
II. Inmersión por eficiencia
51. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 14
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Diseño de recursividad por inmersión
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
A veces el diseño de una función recursiva se expresa como una invocación concreta de
una función más general que incluye parámetros adicionales. Esta técnica, conocida por
el nombre de diseño por inmersión, se aplica por dis6ntas cues6ones que discu6remos a
con6nuación
Objetivos
Recorrido
Táctica
Diseño
Eficiencia
R. Final
Acumulación Resultados
S e a p l i c a p a r a o b t e n e r
recurrencias con estructuras de
datos está6cas o parámetros
constantes durante la ejecución
-
-
-
-
-
Esta tác6ca de inmersión se aplica
para precalcular y acumular un
valor de entrada de manera que se
ahorre en 6empo o memoria
Se incluyen parámetros de
acumulación para evitar tener que
combinar tras la ejecución de las
recursiones de cada subproblema
Esta tác6ca de inmersión se aplica
para calcular y u6lizar un resultado
parcial, que viene de una llamada
posterior en la cadena recursiva
52. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 15
Diseño de algoritmos recursivos
Diseño de algoritmos recursivos
Ejercicios
Como hemos visto, la tarea de diseño de una función recursiva consiste en la definición de
la colección de casos base y casos recursivos que resuelvan sa6sfactoriamente el problema.
A con6nuación discu6mos el correcto diseño de cada 6po de caso
Diseñe una función que calcule el
factorial de un número. Determine el
6po de recursividad de que se trata
según las 3 clasificaciones anteriores
I. Función factorial
Cada valor de la serie de fibonacci se
ob6ene a par6r de la suma de los dos
anteriores. Los dos primeros
elementos de la serie son 1
II. Serie de fibonacci
Calcule la n-esima potencia de un
número mediante el diseño de una
función recursiva. Clasifique el diseño
con respecto a los criterios anteriores
III. Potencia de un número
Diseñe una función recursiva que
calcule la suma de los n primeros
números naturales. ¿Es recursiva
simple? ¿es final?
IV. Suma de N naturales
Diseñe una función recursiva que
calcule la suma de los n primeros
elementos de un vector de enteros.
Clasifique la función
V. Suma de un vector
Diseñe una función recursiva que
calcule el producto escalar de dos
vectores de enteros. Clasifique la
función
VI. Producto escalar
Diseñe una función recursiva que
busque un elemento dentro de un
vector de enteros. Clasifique la
función
VII. Búsqueda en vector
Diseñe un predicado recursivo que
determine si un vector de enteros
con6ene o no algún elemento
repe6do
VIII. Elementos repetidos
Diseñe una función recursiva que
calcule el máximo común divisior
entre dos enteros por aplicación del
algoritmo de Euclides
IX. Máximo común divisor
53. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 16
Diseño de algoritmos itera6vos
¿Qué son los algoritmos itera8vos?
En los algoritmos itera6vos los problemas se resuelven mediante la escritura de una
colección de instrucciones de propósito específico que se ejecutan de manera secuencial
según el orden en que se han escrito. Algunas de estas instrucciones permiten alterar el
control secuencial de la ejecución para ar6cular flujos itera6vos o condicionales de
ejecución
Esquema general de un algoritmo itera8vo
int está (T[] v, T e) {
int index = 0;
boolean found = false;
while (!found && index < v.length) {
found = (v [index] == e);
if (!found) index++;
}
if (found) return index;
else return -1;
}
La inicialización es el paso
preliminar para proceder con el
diseño itera6vo de algoritmos
Inicialización
Iteración
Los algoritmos itera6vos basan su
funcionamiento en iteraciones de
bloques de código generalmente
aplicadas sobre elementos de
estructuras de datos
Bifurcación
Las instrucciones de control de
flujo condicional permiten ejecutar
sentencias solo bajo determinadas
condiciones ambientales
Secuenciamiento
La caracterís6ca esencial del diseño itera6vo radica en el
concepto de secuencia de instrucciones ejecutadas en orden
y en el uso de variables para acumular estados parciales
54. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 17
Diseño de algoritmos itera6vos
Diseño de algoritmos itera8vos
El diseño itera6vo u6liza instrucciones que prescriben cómo realizar los cálculos o tareas
necesarias para llegar al resultado buscado. Estas instrucciones se ejecutan de acuerdo a
flujos de ejecución, que pueden ser secuenciales, bifurca6vos e itera6vos. La u6lización de
variables y la sentencia de asignación juegan un papel preponderante
Elementos de un algoritmo itera88vo
Elementosdelos
algoritmos
iterativos
I. Sentencias de asignación
II. Sentencias de control de flujo
A. Encadenamiento secuencial
B. Control de flujo condicional
C. Control de flujo iterativo
La sentencia de asignación juegan un papel preponderante en el diseño
itera6vo ya que permite acumular cálculos parciales que representan el
estado del algoritmo en ese punto
La ejecución de instrucciones
puede ar6cularse en secuencia,
bifurca6vamente o en iteración.
Existen sentencias que permiten
determinar el control de flujo
Las instrucciones se encadenan secuencialmente
para que se ejecuten una detrás de otra
Las instrucciones se agrupan en dos bloques que
se ejecutan alterna6vamente si se sa6sface una
condición
Las instrucciones se agrupan en un bloque que se
ejecuta itera6vamente mientras se sa6sface una
condición
55. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 18
Diseño de algoritmos itera6vos
Diseño de algoritmos itera8vos
El diseño itera6vo u6liza instrucciones que prescriben cómo realizar los cálculos o tareas
necesarias para llegar al resultado buscado. Estas instrucciones se ejecutan de acuerdo a
flujos de ejecución, que pueden ser secuenciales, bifurca6vos e itera6vos. La u6lización de
variables y la sentencia de asignación juegan un papel preponderante
Sentencia de asignación
Sentencia;
variable = expresión;
Sentencia;
En el diseño itera6vo las variables representan almacenes de datos en memoria que
con6enen el valor resultante del cómputo de una expresión. Este valor representa
parcialmente el estado del algoritmo en 6empo de ejecución en función de los
elementos de entrada
Asignación
A diferencia de cómo ocurre
en algoritmos recursivos las
sentencias de asignación
permiten apoyarse en
variables para que sean
referidas posteriormente
desde otros puntos del
algoritmo
Estado
Cada sentencia
supone un cambio
potencial en el
estado de la
máquina. La
asignación permite
recogerlo
parcialmente en el
valor de la variable
Expresión y variable
La variable es una referencia
simbólica a un especio reservado
en memoria. La expresión una
fórmula que permite calcular un
valor en función de otras variables
y constantes
56. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 19
Diseño de algoritmos itera6vos
Diseño de algoritmos itera8vos
El diseño itera6vo u6liza instrucciones que prescriben cómo realizar los cálculos o tareas
necesarias para llegar al resultado buscado. Estas instrucciones se ejecutan de acuerdo a
flujos de ejecución, que pueden ser secuenciales, bifurca6vos e itera6vos. La u6lización de
variables y la sentencia de asignación juegan un papel preponderante
Encadenamiento secuencial
Sentencia;
Sentencia;
Sentencia;
El modelo de ejecución por defecto es la ejecución secuencial. Según éste, las
instrucciones son lanzadas a ejecución de acuerdo al orden en que aparecen
correla6vamente escritas en el algoritmo
Encadenamiento secuencial
El delimitador de sentencias separa una
sentencia de la siguiente dentro de un bloque
de instrucciones secuencial y puede ser
considerado como el operador que ar6cula el
encadenamiento secuencial
Ejecución en secuencia
La ejecución en secuencia se alinea con la idea de que
cada sentencia realiza un paso del algoritmo hacia la
obtención del resultado final y con la descomposición
funcional descendente del paradigma estructurado
57. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 20
Diseño de algoritmos itera6vos
Diseño de algoritmos itera8vos
El diseño itera6vo u6liza instrucciones que prescriben cómo realizar los cálculos o tareas
necesarias para llegar al resultado buscado. Estas instrucciones se ejecutan de acuerdo a
flujos de ejecución, que pueden ser secuenciales, bifurca6vos e itera6vos. La u6lización de
variables y la sentencia de asignación juegan un papel preponderante
Control de flujo condicional
if (expresión-lógica ) {
<< bloque-sentencias>>
} else {
<< bloque-sentencias>>
}
Las sentencias de control de flujo condicional alteran la ejecución normal – secuencial –
de un algoritmo para generar dis6ntas bifurcaciones ejecutables en función de ciertas
condiciones ambientales
If – Then – Else
Se evalúa la expresión lógica. Si el resultado es
cierto se ejecuta el primer bloque de sentencias.
Si es falso se ejecuta el segundo bloque de
sentencias
switch (expresión) {
case cte-1: <<bloque-sentencias>> break;
case cte-2: <<bloque-sentencias>> break;
...
default: <<bloque-sentencias>>
}
Switch - Case
Se evalúa la expresión. Si coincide con la
constante del caso i se ejecuta el bloque de
sentencias adjunto. Si no se ajusta a ningún caso
se ejecuta el bloque de sentencias default
58. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 21
Diseño de algoritmos itera6vos
Diseño de algoritmos itera8vos
El diseño itera6vo u6liza instrucciones que prescriben cómo realizar los cálculos o tareas
necesarias para llegar al resultado buscado. Estas instrucciones se ejecutan de acuerdo a
flujos de ejecución, que pueden ser secuenciales, bifurca6vos e itera6vos. La u6lización de
variables y la sentencia de asignación juegan un papel preponderante
Control de flujo itera8vo
for (asignación-índice;
expresión-límite;
expresión-incremento) {
<< bloque-sentencias>>
}
Las sentencias de control de flujo itera6vo alteran la ejecución normal – secuencial – de
un algoritmo para generar dis6ntas iteraciones sobre un cuerpo de sentencias. El
número de iteraciones depende de condiciones ambientales
For
Iteración de bloque de sentencias
controlada por índice. El valor
inicial se indica en asignación-
índice, el incremento en expresión-
incremento y termina cuando
expresión-límite se hace falso
<<inicialización>>
while (expresión-lógica ) {
<< bloque-sentencias>>
<< incremento>>
}
While
Iteración de bloque se sentencias
mientras expresión-lógica sea
cierta. Inicialización externa al
bucle. Incremento explícito
picamente al final del bloque de
sentencias
<<inicialización>>
do {
<< bloque-sentencias>>
<< incremento>>
} while (expresión-lógica );
Do - While
Iteración de bloque de sentencias.
Inicialización exterior. Incremento
picamente al final del bloque.
Comprobación lógica al final de
cada iteración. Una ejecución al
menos
59. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 22
Diseño de algoritmos itera6vos
Diseño de algoritmos itera8vos
El diseño itera6vo u6liza instrucciones que prescriben cómo realizar los cálculos o tareas
necesarias para llegar al resultado buscado. Estas instrucciones se ejecutan de acuerdo a
flujos de ejecución, que pueden ser secuenciales, bifurca6vos e itera6vos. La u6lización de
variables y la sentencia de asignación juegan un papel preponderante
Ejercicios
Encuentre una solución itera6va para
cada uno de los problemas que se
presentaron con anterioridad
I. Función factorial
II. Serie de fibonacci
III. Potencia de un número
IV. Suma de N naturales
V. Suma de un vector
VI. Producto escalar
VII. Búsqueda en vector
VIII. Elementos repetidos
IX. Máximo común divisor
// Pre: -1 < j <= length
public int sumaV (int[] v) {
int j = 0;
int s = 0;
while (j < v.length) {
s = s + v[j];
j++;
}
return s;
}
// Post: s = Σ v[i]
i=0
length
60. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 23
Traducción de algoritmos recursivos a itera6vos
Traducción de algoritmos recursivos a itera8vos
Los algoritmos recursivos aunque elegantes y eficaces han presentado problemas históricos
de computabilidad ya que el soporte por parte de los compiladores a la invocación recursiva
de programas es rela6vamente reciente. Merece la pena discu6r procedimientos de
transformación de algoritmos recursivos a itera6vos
Traducción de algoritmos con recursividad final
public int sumaV (int[] v, int j, int w) {
if (j >= n) return w
else return sumaV (v, j+1, v[j] + w)
}
public int sumaVit (int [n] v) {
int j = 0;
int w = 0;
while (j < n) {
w = w + v[j];
j = j + 1;
}
return w;
}
Los parámetros de entrada se subs6tuyen por
variables locales con el valor que recibirían en la
llamada inicial (j). El parámetro acumulador (w)
juega el papel del resultado parcial inicialmente 0.
Dentro del bucle se calcula el valor,
en cada paso, de las variables de
resultado parcial w y de recorrido j
61. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 24
Traducción de algoritmos recursivos a itera6vos
Traducción de algoritmos recursivos a itera8vos
Los algoritmos recursivos aunque elegantes y eficaces han presentado problemas históricos
de computabilidad ya que el soporte por parte de los compiladores a la invocación recursiva
de programas es rela6vamente reciente. Merece la pena discu6r procedimientos de
transformación de algoritmos recursivos a itera6vos
Traducción de algoritmos con recursividad no final
public int factorial( int n ) {
if (n == 0) return 1;
else return n * factorial ( n - 1 );
}
public int factIt (int n) {
int i = n;
while (i > 0) {
i = i - 1
}
int r = 1;
while (i < n) {
r = r * i;
i++;
}
return r
}
Buscar en i el final de la cadena de llamadas
descendente. Se aplica en cada vuelta el sucesor
de los parámetros (n-1) hasta encontrar el
equivalente al tamaño del caso trivial (0).
Se usa r para acumular el resultado. Se inicializa
al resultado del caso base. Se usa la variable i
como objeto de comparación del segundo
bucle. Se computa el resultado parcial aplicando
la función de combinación (*) por el valor del
parámetro. Al final se devuelve el resultado
62. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 25
Traducción de algoritmos recursivos a itera6vos
Traducción de algoritmos recursivos a itera8vos
Los algoritmos recursivos aunque elegantes y eficaces han presentado problemas históricos
de computabilidad ya que el soporte por parte de los compiladores a la invocación recursiva
de programas es rela6vamente reciente. Merece la pena discu6r procedimientos de
transformación de algoritmos recursivos a itera6vos
Traducción de algoritmos mediante el uso de una pila
int invertir (int n, int r) {
if (n == 0) return r;
return invertir ((n / 10), r * 10 + n % 10);
}
int invertirIt (int n) {
int j = n;
Stack <int> p=new Stack <int>();
while (j > 10) {
p.push (j);
n = n / 10;
}
int k = j;
while (!p.isEmpty ()) {
j = p.top();
p.pop();
k = k + (j % 10);
}
return k }
Inicialización de j como
variable local que
representa el valor inicial
del parámetro y de p como
pila vacía de trabajo
Apilamos el valor en curso de j para
recuperarlo a la vuelta y calculamos el
sucesos (n/10)
Hemos terminado la cadena descendente de
llamadas. Ahora preparamos la cadena
ascendente de vuelta. k llevará el resultado,
que parte del valor de j cuando termina el
bucle de ida
63. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 26
Catálogo de algoritmos
Catálogo de algoritmos
Aunque encontrar un catálogo de algoritmos canónicos y recurrentes es complejo dado su
gran diversidad, si relacionamos el diseño de algoritmos con los principales 6pos abstractos
de datos que se presentaron en el tema anterior, es posible encontrar 3 categorías
generales en la que éstos caen principalmente de acuerdo a su propósito
Catálogo de
algoritmos
I. Algoritmos de recorrido
II. Algoritmos de búsqueda
III. Algoritmos de ordenación
El propósito de los algoritmos de recorrido es encontrar una expresión lineal de
los elementos almacenados en la estructura de datos. Dependiendo de ésta
puede haber varias estrategias de recorrido alterna6vas. El resultado es una
colección ordenada de los elementos de la estructura
El propósito de los algoritmos de búsqueda es encontrar una elemento de entre
todos los elementos almacenados en la estructura de datos. Dependiendo de
ésta existen dis6ntas estrategias con complejidad viceversa. El resultado es un
valor de verdad indicado si se encuentra el elemento o un índice de posición
El propósito de los algoritmos de ordenación es reorganizar los elementos de la
estructura de datos para disponerlos de acuerdo a cierto criterio de orden.
Para poder ar6cular una ordenación sobre una estructura de datos los
elementos deben ser comparables y la estructura prestarse al criterio de orden
64. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 27
Catálogo de algoritmos
Catálogo de algoritmos
La naturaleza itera6va o recursiva de los algoritmos quede frecuentemente inducida por la
forma en que el perfil de las operaciones da acceso a los datos. A lo largo de este curso
repasaremos los principales 6pos de algoritmos – recorrido, búsqueda y ordenación –
aplicables sobre cada uno de los 6pos abstractos de datos que estudiaremos
Recorrido Búsqueda Ordenación
Listas*
Pilas
Colas
Arboles
Recorrido directo
Recorrido inverso
Búsqueda secuencial
Inserción
Merge sort
Recorrido desde la cima
Búsqueda secuencial
-
Recorrido hacia el final
Búsqueda secuencial
-
Preorden, inorden,
postorden
Recorrido en anchura
Búsqueda binaria
Ordenación
* Se refiere a listas, listas doblemente
enlazadas y listas circulares
65. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 28
Bibliograha
BibliograOa
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
66. Estrategias de programación
Javier Vélez Reyes jvelez@lsi.uned.es2 - 29
Bibliograha
BibliograOa
Bibliografía complementaria
Programación metódica. BALCÁZAR, J. L.
McGraw-Hill, 1993. ISBN 8448119576
Diseño de programas. Formalismo y
abstracción. Ricardo Peña Marí. Pearson -
Prentice Hall. ISBN 13: 9788420541914
68. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 2
Índice
Índice
› Introducción
› ¿Qué es la eficiencia de los algoritmos?
› Criterios de clasificación del análisis de la eficiencia
› Métricas de análisis de la eficiencia de los algoritmos
› Medida de la eficiencia de los algoritmos
› ¿Cómo se mide la eficiencia de los algoritmos?
› Medida asintótica de la eficiencia
› Órdenes de complejidad
› Bibliografía
69. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 3
Obje6vos generales
Obje8vos
› Aprender qué es la eficiencia de los algoritmos
› Aprender los criterios en torno a los cuales se puede clasificar la eficiencia
› Conocer las principales métricas de medida de la eficiencia
› Aprender cómo se puede calcular el coste de un algoritmo bajo 3 supuestos
› Medida del tiempo de ejecución
› Medida asintótica O
› Hipótesis de caso peor
› Aprender cómo se mide la eficiencia algorítmica de
› Algoritmos recursivos
› Algoritmos iterativos
› Adquirir una visión crítica sobre la complejidad algorítmica
› Adquirir herramientas para seleccionar el mejor algoritmo para un problema
› Adquirir herramientas para seleccionar la estructura más eficiente para un problema
70. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 4
Introducción
¿Qué es la eficiencia de los algoritmos?
El análisis de la eficiencia de los algoritmos permite establecer criterios compara6vos y
clasificatorios entre algoritmos que ayudan a entender cómo se comportan y escalan éstos
en cuanto a la consumición de recursos – 6empo y memoria fundamentalmente – con
respecto a la magnitud de sus parámetros de entrada
Definición
El análisis de la eficiencia de los algoritmos es un estudio teórico, formal, compara6vo e
independiente de la implementación que 6ene por objeto clasificar a los algoritmos en
familias de complejidad de acuerdo a cómo se comportan según crece la magnitud de
sus parámetros de entrada
› Estudio formal
› Teórico
› Comparativo
› Clasificatorio
› De recursos de máquina
› Del lenguaje de programación
› De aspectos constantes
› De aspectos de escala
Estudio teórico Independencia
71. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 5
Introducción
¿Qué es la eficiencia de los algoritmos?
El análisis de la eficiencia de los algoritmos permite establecer criterios compara6vos y
clasificatorios entre algoritmos que ayudan a entender cómo se comportan y escalan éstos
en cuanto a la consumición de recursos – 6empo y memoria fundamentalmente – con
respecto a la magnitud de sus parámetros de entrada
boolean contiene (T[] v, int p, T e) {
int i = p;
boolean found = false
while (!found && i <= v.length) {
found = (v[i] == e);
i = i + 1;
}
return found; }
boolean repetidos (T[] v) {
boolean repetidos = false;
int i = 0;
while (!repetidos && i < v.length)
repetidos = contiene (v, i+1, v[i]);
return repetidos;
}
boolean ordenar (T[] v) {
int temp;
for (int i = 1; i < v.length; i++)
for (int k = v.length - 1; k >= i; k--)
if (v[k] < v[k-1]) {
temp = v[k];
v[k] = v[k-1];
v[k-1] = temp;
}
}
<
tiempo
72. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 6
Introducción
¿Qué es la eficiencia de los algoritmos?
El análisis de la eficiencia de los algoritmos permite establecer criterios compara6vos y
clasificatorios entre algoritmos que ayudan a entender cómo se comportan y escalan éstos
en cuanto a la consumición de recursos – 6empo y memoria fundamentalmente – con
respecto a la magnitud de sus parámetros de entrada
Criterios de medida de la eficiencia
Criteriosdemedida
I. Según el tipo de recurso
II. Según el tipo de comportamiento
II. Según la métrica utilizada
La eficiencia de los algoritmos puede medirse
de acuerdo a la consumición de diferentes
recursos. La medida de la eficiencia de un
algoritmo puede ser distinta según el recurso
Espacial
Temporal
Otros
Se analiza la relación funcional existente entre
el tamaño del problema expresado en términos
de sus parámetros de entrada y la consumición
del recurso memoria
Se analiza la relación funcional existente entre
el tamaño del problema expresado en términos
de sus parámetros de entrada y la consumición
del recurso tiempo de cómputo
Foco de
atención
}
Se analiza la relación funcional existente entre
el tamaño del problema expresado en términos
de sus parámetros de entrada y la consumición
de otros recursos como periféricos empleados,
ancho de banda, consumo eléctrico, etc.
Fijado un tipo de recurso, la eficiencia de los
algoritmos puede medirse bajo distintos
supuestos en los que se supone se encuentra
el problema medio a analizar
Fijado un tipo de recurso y un determinado
supuesto, debe escogerse una métrica
comparativa que permita clasificar a los
algoritmos en familias con un comportamiento
interno similar
73. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 7
Introducción
¿Qué es la eficiencia de los algoritmos?
El análisis de la eficiencia de los algoritmos permite establecer criterios compara6vos y
clasificatorios entre algoritmos que ayudan a entender cómo se comportan y escalan éstos
en cuanto a la consumición de recursos – 6empo y memoria fundamentalmente – con
respecto a la magnitud de sus parámetros de entrada
Criterios de medida de la eficiencia
Criteriosdemedida
I. Según el tipo de recurso
II. Según el tipo de comportamiento
II. Según la métrica utilizada
La eficiencia de los algoritmos puede medirse
de acuerdo a la consumición de diferentes
recursos. El tipo de recurso establece una
partición del espacio de algoritmos distinta
Peor caso
Caso medio
Mejor caso
Se estima la máxima cantidad de recursos que
un algoritmo puede necesitar consumir para su
ejecución en función de su entrada. Supone
una cota superior de estos recursos
Se estima el comportamiento a partir de una
hipótesis sobre la distribución estadística de los
datos de entrada que se supone más probable.
También llamado análisis probabilístico
Foco de
atención
}
Se estiman los recursos necesarios para su
ejecución en condiciones óptimas en función de
la entrada. Esta medida afecta al ejemplar más
sencillo del problema
Fijado un tipo de recurso, la eficiencia de los
algoritmos puede medirse bajo distintos
supuestos en los que se supone se encuentra
el problema medio a analizar
Fijado un tipo de recurso y un determinado
supuesto, debe escogerse una métrica
comparativa que permita clasificar a los
algoritmos en familias con un comportamiento
interno similar
.
74. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 8
Introducción
¿Qué es la eficiencia de los algoritmos?
El análisis de la eficiencia de los algoritmos permite establecer criterios compara6vos y
clasificatorios entre algoritmos que ayudan a entender cómo se comportan y escalan éstos
en cuanto a la consumición de recursos – 6empo y memoria fundamentalmente – con
respecto a la magnitud de sus parámetros de entrada
Criterios de medida de la eficiencia
Criteriosdemedida
I. Según el tipo de recurso
II. Según el tipo de comportamiento
II. Según la métrica utilizada
La eficiencia de los algoritmos puede medirse
de acuerdo a la consumición de diferentes
recursos. El tipo de recurso establece una
partición del espacio de algoritmos distinta
Cota superior. O
Cota inferior. Ω
Cota exacta. Θ
Se mide el coste asintótico de la ejecución de
un algoritmo de acuerdo a una cota superior. Es
decir, la ejecución nunca, a partir de cierto
valor, sobrepasará la cota de coste establecida
Se mide el coste asintótico de la ejecución de
un algoritmo de acuerdo a una cota inferior. Es
decir, la ejecución nunca, a partir de cierto
valor, será menor que la cota establecida
Foco de
atención
}
Se mide el coste asintótico de la ejecución de
un algoritmo de acuerdo a una cota resultante
de la intersección entre O y Ω. Es decir, la
ejecución crece al ritmo de la cota establecida
Fijado un tipo de recurso, la eficiencia de los
algoritmos puede medirse bajo distintos
supuestos en los que se supone se encuentra
el problema medio a analizar
Fijado un tipo de recurso y un determinado
supuesto, debe escogerse una métrica
comparativa que permita clasificar a los
algoritmos en familias con un comportamiento
interno similar
.
75. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 9
Introducción
¿Qué es la eficiencia de los algoritmos?
El análisis de la eficiencia de los algoritmos permite establecer criterios compara6vos y
clasificatorios entre algoritmos que ayudan a entender cómo se comportan y escalan éstos
en cuanto a la consumición de recursos – 6empo y memoria fundamentalmente – con
respecto a la magnitud de sus parámetros de entrada
Métricas de análisis de la eficiencia de los algoritmos
Cota superior. O
Si g(n) es la función de coste de un
algoritmo, se dice que g(n) está en
O(f(n)) si a partir de un cierto punto
crece, a lo sumo, menos rápido que
f(n). Es decir, la gráfica de g está por
debajo de la de f
.
Cota inferior. Ω
Si g(n) es la función de coste de un
algoritmo, se dice que g(n) está en
Ω(f(n)) si a partir de un cierto punto
crece más rápido que f(n). Es decir,
la gráfica de g está por encima de la
de f)
Cota exacta. Θ
Si g(n) es la función de coste de un
algoritmo, se dice que g(n) está en
Θ(f(n)) si crece de la misma forma (al
mismo ritmo) que f(n)
76. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 10
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de los algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Medida asintó8ca de la eficiencia
.
Tiempo medido
A * n + B
A * 2n + B
A * 3n + B
...
A * kn + B
Búsqueda de un elemento en un vector
Si hacemos medidas expe-
rimentales sobre sucesivas
ejecuciones de un algorit-
mo y en cada ejecución
duplicamos el tamaño del
problema, observamos que
el 6empo de ejecución
también se duplica. En ese
caso se puede decir que el
c o s t e a s i n t ó 6 c o d e l
algoritmo es lineal
Tiempo de ejecución
El tamaño del problema es proporcional al número de elementos que
contiene el vector. Sin embargo el tiempo de ejecución no se ve
afectado por constantes multiplicativas o sumativas ya que el coste
temporal se duplica al duplicar el tamaño del problema
t
2t
3t
...
kt
O (n)
n
2n
3n
...
kn
Tamaño
77. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 11
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de la algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Ordenes de eficiencia
.
El análisis asintó6co nos permite
clasificar el espacio de algoritmos en
dis6ntas familias que se corresponden
con órdenes de complejidad diferentes
Constante. O (1)
Logarítmica. O (log n)
Cuadrática inversa. O (√n)
Lineal. O (n)
Cuasilineal. O (n log n)
Cuadrática. O (n2)
Cúbica. O (n3)
Polinómica de grado k. O (nk)
...
Exponencial. O (2n)
...
Exponencial de grado k. O (kn)
Factorial. O (n!)
Hiperexponencial. O (nn)
int factorial (int n) {
if (n == 0) return 1;
else return n * factorial (n - 1);
}
78. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 12
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de la algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Ordenes de eficiencia
.
C a d a o r d e n d e e fi c i e n c i a
representa un nivel de crecimiento
con respecto al tamaño del
problema. En la gráfica adjunta
p u e d e v e r s e l a r e l a c i ó n
compara6va de los niveles de
crecimiento de los primeros
órdenes de eficiencia anteriores
79. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 13
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de la algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Ordenes de eficiencia
.
C a d a o r d e n d e e fi c i e n c i a
representa un nivel de crecimiento
con respecto al tamaño del
problema. En la gráfica adjunta
p u e d e v e r s e l a r e l a c i ó n
compara6va de los niveles de
crecimiento de los órdenes de
eficiencia siguientes a n2
80. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 14
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de los algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Algoritmos recursivos
.
El cálculo del coste temporal de un algoritmo recursivo se expresa en términos del coste
de los casos base y los casos de recursión del mismo. Para ilustrar cómo se procede
consideremos la función del cálculo de un número factorial en su versión recursiva.
Entonces, si u6lizamos T(n) para representar el coste de computar la ejecución con
tamaño n…
int factorial (int n) {
if (n == 0) return 1;
else return n * factorial (n - 1);
}
T (n) =
C1 si n == 0
T (n-1) + C2 si n > 0
Coste caso base
Coste caso recurrente
Resolución para factorial (5):
T(5) = T(4) + C2 = T(3) + C2 + C2 = T(2) + C2 + C2 + C2 = T(1) + C2 + C2 + C2 + C2
= T(0) + C2 + C2 + C2 + C2 + C2 = C1 + C2 + C2 + C2 + C2 + C2 = C1 + 5 * C2
≈ O(n)
Dado que el coste temporal
resulta linealmente propor-
cional al tamaño del proble-
ma el orden de complejidad
es lineal
}
81. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 15
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de los algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Algoritmos recursivos
.
Para evitar en cada caso un razonamiento
similar al anterior, podemos derivar una
fórmula general de cálculo en función de la
estructura de la función recursiva, solución
analí6ca de la ecuación de recurrencias
adjunta
i: Número máximo de invocaciones recursivas por caso
d: Factor de decrecimiento del problema en la división del problema
n < d : Caso base
n >= d : Caso recursivo
c1·nk, c2·nk : Coste asociados a las partes no recursivas
k : Nivel de dependencia de las operaciones no recursivas con el tamaño del problema
0 : Constante
1 : Lineal
2 : Cuadrática
T (n) =
c1·nk si n < d
i·T(n ± d) + c2·nk si n >= d
82. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 16
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de los algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
.
Si ± reducción por substracción – Si ± reducción por división /
T (n) ≈
O (nk+1) si i == 1
O (in/d) si i > 1
T (n) ≈
O (nk) si i < dk
O (nlog
d
i) si i > dk
O (nk log n) si i = dk
Algoritmos recursivos
Para evitar en cada caso un razonamiento
similar al anterior, podemos derivar una
fórmula general de cálculo en función de la
estructura de la función recursiva, solución
analí6ca de la ecuación de recurrencias
adjunta
T (n) =
c1·nk si n < d
i·T(n ± d) + c2·nk si n >= d
83. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 17
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de los algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Algoritmos itera8vos
.
El coste temporal de un algoritmo itera6vo se calcula acumula6vamente a par6r del coste
de cada una de sus instrucciones cons6tuyentes. Estudiemos su coste
1 Las Operaciones básicas no
dependen del tamaño del problema
Instrucción
Operaciones básicas1
- Entrada / salida
- Asignación
- Expresiones escalares
Secuencias sentencias
- s1; s2; s3
Sentencias condicionales
- if (e) {b1} else {b2}
- switch (e) {
case c1 : b1;
case c2 : b2;
}
Coste
O(1)
O(1)
O(1)
Σ O(si) = max {O (si)}
max {O(e), O(b1), O(b2)}
max {O(e), O(b1), O(b2)}
Instrucción
Sentencias iterativas
- for (ini;e;inc) {b}
- while (e) {b}
- do {b} while (e)
Invocación subprogramas
- f (e1, e2)
Reglas de producto y suma
- O (f + g)
- O (f * g)
Coste
max {O(ini), n· max {O(e), O(inc), O(b)}}
n· max {O(e), O(b)}
n· max {O(e), O(b)}
Max {O(e1), O(e2), O(f)}
O(f + g) = max (O(f), O(g))
O(f * g) = O(f) * O(g)
84. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 18
Medida de la eficiencia de los algoritmos
¿Cómo se mide la eficiencia de los algoritmos?
La medida de la eficiencia asintó6ca de algoritmos pretende clasificar cada algoritmo en
una familia de complejidad asintó6ca determinada prescindiendo de consideraciones
constantes o de escala. En nuestro estudio u6lizaremos medida temporal, caso peor y cota
superior
Algoritmos itera8vos
.
A par6r de los análisis anteriores de coste
de cada instrucción analicemos la
eficiencia de un algoritmo itera6vo
boolean ordenar (T[] v) {
int temp;
for (int i = 1; i < v.length; i++) O(1)
for (int k = i+1; k < v.length; k++) O(1)
if (v[i] < v[k]) { O(1) O(n2)
temp = v[k]; O(1)
v[k] = v[i]; O(1) O(1) O(1)·(n-i) O(n)·n
v[i]= temp; O(1)
}
}
max max max max
86. Análisis de la eficiencia de los algoritmos
Javier Vélez Reyes jvelez@lsi.uned.es3 - 20
BibliograWa
BibliograJa
Bibliografía complementaria
Fundamentos de Algoritmia. G. Brassard, P.
Bratley. Prentice Hall. SBN: 84-89660-00-X
1997
Diseño de programas. Formalismo y
abstracción. Ricardo Peña Marí. Pearson -
Prentice Hall. ISBN 13: 9788420541914
88. Tipos Abstractos de Datos
Javier Vélez Reyes jvelez@lsi.uned.es4 - 2
Índice
Índice
› Introducción
› ¿Qué son los tipos abstractos de datos?
› Especificación de tipos abstractos de datos
› Tipos Abstractos de Datos
› Catálogo de tipos abstractos de datos
› Diseño de tipos abstractos de datos
› Bibliografía
89. Tipos Abstractos de Datos
Javier Vélez Reyes jvelez@lsi.uned.es4 - 3
Obje6vos generales
Obje8vos
› Aprender qué son los tipos abstractos de datos
› Aprender cómo se construyen tipos abstractos de datos
› Dentro del paradigma estructurado
› Dentro del paradigma de orientación a objetos
› Conocer los distintos tipos abstractos de datos que existen
› Aprender a aplicar tipos abstractos de datos en problemas reales
› Valorar el avance conceptual que supone trabajar con abstracciones de datos
› Obtener una actitud critica para valorar el uso y diseño de tipos abstractos de datos
› Entender la relación existe entre la naturaleza de los tipos abstractos de datos y
› Las estrategias de implementación recursivas o iterativas que conviene aplicar
› La complejidad algorítmica inherente que supone su implementación
› Entender el valor preponderante de las abstracciones de datos estudiadas
› Aprender a adaptar dichas abstracciones a cada problema particular
90. Tipos Abstractos de Datos
Javier Vélez Reyes jvelez@lsi.uned.es4 - 4
Introducción
¿Qué son los 8pos abstractos de datos?
Definiciones
La caracterización formal y precisa de lo que entenderemos en este curso por 6po abstracto
de datos parte de una diferenciación previa fundamental entre tres conceptos: 6po
abstracto de datos, 6po de datos y estructura de datos
Una estructura de datos es una representación computacional de la
organización de un conjunto de datos ar6culada en términos de 6pos de
datos primi6vos y otras estructuras o 6pos del lenguaje
Un 6po de datos es la definición de una estructura de datos por parte del
usuario programador para incluirla como un nuevo concepto nominal que
forme parte de las en6dades semán6cas del problema
Un 6po abstracto de datos es un modelo formal de organización de datos
caracterizado por cierto comportamiento semán6co definido en términos
de una colección de propiedades axiomá6cas y operaciones. Dicho
modelo es prescrip6vamente independiente de sus posibles
implementaciones subyacentes y responde a un patrón de uso recurrente
I. Estructura de Datos
II. Tipo de datos
III. Tipo abstracto de datos
- Book elements []
+ void push (Book b) {...}
+ Book pop () {...}
BookStack
T elements []
Stack <T>
+ void push (T e)
+ T pop ()
91. Tipos Abstractos de Datos
Javier Vélez Reyes jvelez@lsi.uned.es4 - 5
Introducción
Especificación de 8pos abstractos de datos
Partes de la especificación de 8pos abstractos de datos
La construcción de 6pos abstractos de datos comienza por la especificación formal de un
conjunto de operaciones que definen el comportamiento del 6po. Cada operación del 6po
se define sintác6camente por un perfil y semán6camente por un contrato. Por extensión
llamaremos perfil y contrato de un 6po abstracto de datos al formado, respec6vamente,
por todas sus operaciones
El perfil de cada operación describe la sintaxis de la
misma indicando su nombre, 6po y nombre de cada
parámetro de entrada y / o salida y el 6po de retorno
de la misma
I. Parte sintác8ca
II. Parte semán8ca
Especificación de
un 8po abstracto
de datos
El contrato de cada operación describe en términos
formales abstractos el comportamiento esperado de
la misma tras su operación y el conjunto de valores
legí6mos que es posible aplicar a cada parámetro
formal para realizar la invocación
92. Tipos Abstractos de Datos
Javier Vélez Reyes jvelez@lsi.uned.es4 - 6
Introducción
Las operaciones consultoras deben garan6zar que no provocaran
un cambio en el estado interno de la abstracción ya que de no ser
así la semán6ca de las operaciones puede verse comprome6da
desde la perspec6va de los usuarios de la abstracción
I. Separación entre operaciones consultoras y modificadoras
stack.pop () + stack.pop ()
!= 2 * stack.pop ()
Los parámetros que debe recibir una operación deben ser solo de
6po operando. Los parámetros de configuración – aquellos para
los que existe un valor por omisión – deben ser proporcionados
previamente mediante la invocación opcional de otras
operaciones de configuración
II. Separación entre parámetros de configuración y operandos
Reglas de especificación
La especificación de perfiles de los 6pos abstractos de datos es una labor delicada que debe
prestar atención a una serie reglas que van dirigidas a evitar efectos colaterales cuando se
invocan las operaciones del 6po abstracto de datos. A con6nuación resumidos las 4 reglas
fundamentales de la especificación
Especificación de 8pos abstractos de datos. Parte Sintác8ca
Stack <T>
+ void push (T element)
+ T pop ()
...
Impresora
+ void imprimir (Trabajo t)
+ void setPapel (int papel)
+ void setColor (boolean c)
+ void set2Caras (boolean c)
L
93. Tipos Abstractos de Datos
Javier Vélez Reyes jvelez@lsi.uned.es4 - 7
Introducción
El número de parámetros formales que debe contener el perfil de
una operación no debe ser mayor de 3. Si la can6dad de
información que se debe proporcionar es mucha considere
realizar abstracciones que encapsulen varios parámetros en uno
III. Tamaño de las operaciones
La especificación del perfil de una abstracción de datos debe ser
realizada de manera que garan6ce que cada operación del 6po
responde a unas responsabilidades que no colisionan con las
responsabilidades de otra/s operaciones. Asimismo, el nivel de
granularidad de las operaciones debe mantenerse homogéneo
entre ellas
IV. Tamaño de las abstracciones
Reglas de especificación
La especificación de perfiles de los 6pos abstractos de datos es una labor delicada que debe
prestar atención a una serie reglas que van dirigidas a evitar efectos colaterales cuando se
invocan las operaciones del 6po abstracto de datos. A con6nuación resumidos las 4 reglas
fundamentales de la especificación
Especificación de 8pos abstractos de datos. Parte Sintác8ca
Trabajo
- idioma
- usuario
- documento
- bandeja
ColaDeImpresión <Trabajo>
+ void imprimir (Trabajo t)
+ void cancelar (trabajo t)
+ void reset ()
+ boolean status ()