Javier	Vélez	Reyes	
				jvelez@lsi.uned.es	
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	
estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	tecnologías	de	la	información	
Departamento	de	Lenguajes	y	Sistemas	informáAcos	
Universidad	Nacional	de	Educación	a	Distancia	
1er Curso
Javier	Vélez	Reyes	
jvelez@lsi.uned.es	
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	.	Grado	en	tecnologías	de	la	información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Parte	I	
Introducción
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Javier	Vélez	Reyes	 		
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
0	Presentación	
Estrategias	de	programación	y	
estructuras	de	datos
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
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
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
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
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
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es	
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
1	Introducción	
Las	estructuras	de	datos	desde	la	
orientación	a	objetos
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
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
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
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
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
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 +
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
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
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
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
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	()
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
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
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
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
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
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
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;
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...
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)
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	[]
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)	
...
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
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
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
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
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
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
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
2	Estrategias	de	
programación	
Algoritmos	iteraAvos	y	recursivos
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
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
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
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
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
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
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
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
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
3	Análisis	de	la	eficiencia	
de	los	algoritmos	
Coste	asintóAco	temporal
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
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
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
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
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
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
.
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
.
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)
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
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);	
}
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
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
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
}
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
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
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)
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
Análisis	de	la	eficiencia	de	los	algoritmos	
Javier Vélez Reyes jvelez@lsi.uned.es3 - 19
BibliograWa	
BibliograJa	
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
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
Javier	Vélez	Reyes		
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
4	
Tipos	Abstractos	
de	Datos	
Estructuras	de	Datos	Básicas
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
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
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	()
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
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
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	()
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 8
Introducción	
Partes	de	un	contrato	
La	especificación	de	un	6po	abstracto	de	datos	también	incluye	la	definición	del	contrato	
para	 cada	 una	 de	 las	 operaciones	 del	 mismo.	 Estos	 contratos	 describen	 el	 efecto	 de	 las	
operaciones	 sobre	 el	 estado	 interno	 del	 6po	 y	 prescriben	 las	 condiciones	 de	 deben	
sa6sfacer	los	parámetros	de	entrada	
pre:	true	
stack.push	(TElement	e)	
post:	stack.nElementos	==	stack’.nElementos	+	1			
						AND	stack.top	()	==	e	
Especificación	de	8pos	abstractos	de	datos.	Parte	Semán8ca	
Las	precondiciones	de	un	contrato	de	operación	
describen	las	condiciones	bajo	las	cuales	puede	
invocarse	 de	 forma	 segura	 la	 misma	 para	
garan6zar	un	futuro	estado	consistente.	Estas	se	
expresan	en	términos	de	los	posibles	valores	de	
cada	parámetro	de	entrada	o	entrada	/	salida	
I.	Precondiciones	
Las	 postcondiciones	 de	 un	 contrato	 de	
operación	 describen	 formalmente	 los	 efectos	
que	provoca	la	invocación.	Éstas	se	describen	a	
par6r	de	los	parámetros	de	entrada	y	salida	de	
las	 operaciones	 y	 de	 las	 variables	 internas	 que	
referencian	 el	 estado	 anterior	 del	 6po	
(U6lizaremos	el	apostrofe	para	referirnos	a	él)	
II.	Postcondiciones
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 9
Tipos	abstractos	de	datos	
Catálogo	de	8pos	abstractos	de	datos	
Los	 6pos	 abstractos	 de	 datos	 canónicos	 que	 aparecen	 recurrentemente	 dentro	 de	 la	
ingeniería	del	soWware	se	pueden	clasificar	según	su	creciente	número	de	restricciones	en	
relación	a	las	polí6cas	de	organización	y	uso	de	sus	datos	internos.	El	siguiente	diagrama	
ilustra	lo	expuesto	
Tipos	abstractos	de	datos	
Estructuras	
sin	orden	
Estructuras	
jerarquías	
Estructuras	
indexadas	
Estructuras	
lineales	
Bolsas	
Conjuntos	
Listas	
Pilas	
Cola	
Árboles	
Grafos	
Estructuras	
circulares	
Listas	circulares	
Enumeración	
Matrices	
Matrices	dispersas	
Estructuras	
tabulares	
Tablas	de	dispersión	
Diccionarios	
+ -Restricciones
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 10
Tipos	abstractos	de	datos	
Catálogo	de	8pos	abstractos	de	datos	
Los	 6pos	 abstractos	 de	 datos	 canónicos	 que	 aparecen	 recurrentemente	 dentro	 de	 la	
ingeniería	del	soWware	se	pueden	clasificar	según	su	creciente	número	de	restricciones	en	
relación	a	las	polí6cas	de	organización	y	uso	de	sus	datos	internos.	El	siguiente	diagrama	
ilustra	lo	expuesto	
Bolsas	
Estructuras	Sin	Orden	
Conjuntos	
-	No	existe	orden	entre	los	elementos	 -	No	existe	orden	entre	los	elementos	
-	No	se	pueden	repe6r	elementos	del	mismo	valor	
1
2
1
2
53
4
1
2
6
7
53
4
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 11
Tipos	abstractos	de	datos	
Catálogo	de	8pos	abstractos	de	datos	
Los	 6pos	 abstractos	 de	 datos	 canónicos	 que	 aparecen	 recurrentemente	 dentro	 de	 la	
ingeniería	del	soWware	se	pueden	clasificar	según	su	creciente	número	de	restricciones	en	
relación	a	las	polí6cas	de	organización	y	uso	de	sus	datos	internos.	El	siguiente	diagrama	
ilustra	lo	expuesto	
Listas	
Estructuras	Linealmente	ordenadas	
Pilas	
-	Existe	un	orden	total	entre	sus	elementos	
-	Existe	un	único	punto	de	ataque	
-	No	existe	destrucción	
3 7 2 4
3 7 2 4 3 7 2 4
3 7 2 4
-	Existe	un	orden	total	entre	sus	elementos	
-	Existe	un	único	punto	de	ataque	llamado	cima	
-	Cima	inmutable	
Primero / Siguiente Punto de interés
Doble enlace Acceso por posición
3
7
2
Colas	
-	Existe	un	orden	total	entre	sus	elementos	
-	Un	punto	de	ataque	para	inserción	y	otro	para	borrado	
-	Cabeza	inmutable	
3 7 2
Pila Cola
Inserción &
borrado
Borrado Inserción
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 12
Tipos	abstractos	de	datos	
Catálogo	de	8pos	abstractos	de	datos	
Los	 6pos	 abstractos	 de	 datos	 canónicos	 que	 aparecen	 recurrentemente	 dentro	 de	 la	
ingeniería	del	soWware	se	pueden	clasificar	según	su	creciente	número	de	restricciones	en	
relación	a	las	polí6cas	de	organización	y	uso	de	sus	datos	internos.	El	siguiente	diagrama	
ilustra	lo	expuesto	
Grafos	
Estructuras	Jerárquicas	
Árboles	Binarios	
-	Un	conjunto	de	nodos	sin	orden	
-	Un	conjunto	de	aristas	sin	orden	
-	Relación	entre	aristas	&	nodos	
-	Variante	de	árbol	general	
-	Cada	nodo	6ene	a	lo	sumo	un	árbol	izquierdo	y	derecho	
Árboles	Binarios	de	Búsqueda	
-	Variante	de	árbol	binario	
-	Los	elementos	se	disponen	en	orden	respecto	a	cada	nodo	
-	La	máxima	diferencia	de	niveles	debe	ser	<=	2	
Arboles	Generales	
-	Un	nodo	raíz	como	punto	de	acceso	
-	Cada	nodo	puede	tener	varios	hijos	
-	Cada	nodo	sólo	6ene	un	padres	
-	El	nodo	raíz	no	6ene	padre	
-	Nodos	hoja	son	nodos	sin	hijos	
3
7
2
37
2
5 49
42
3
97
37
2
49
Árbol de Búsqueda Árbol Binario
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 13
Tipos	abstractos	de	datos	
Diseño	de	8pos	abstractos	de	datos	
Desde	una	perspec6va	de	diseño,	podemos	conceptualizar	todos	los	6pos	abstractos	que	se	
aplican	 en	 el	 marco	 de	 la	 ingeniería	 del	 soWware	 como	 colecciones	 generales	 de	
información.	 A	 par6r	 de	 ahí	 cada	 6po	 abstracto	 de	 datos	 puede	 entenderse	 como	 una	
especialización	 de	 este	 concepto.	 El	 modelo	 UML	 que	 u6lizaremos	 en	 este	 curso	 es	 el	
siguiente	
<<interface>>
CollectionIF<T>
<<interface>>
SetIF<T>
<<interface>>
ListIF<T>
<<interface>>
StackIF<T>
<<interface>>
QueueIF<T>
<<interface>>
TreeIF<T>
<<interface>>
BTreeIF<T>
<<interface>>
IteratorIF<T>
<<interface>>
ComparatorIF<T>
Sorter1
1. Es solo un ejemplo de clase con un método de ordenación
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 14
Tipos	abstractos	de	datos	
Diseño	de	8pos	abstractos	de	datos	
Como	puede	apreciarse	en	el	diagrama	UML	de	clases	anterior,	cada	abstracción	de	datos	
se	representa	por	una	interfaz	que	especializa	las	capacidades	generales	de	una	colección	
abstracta.	 A	 lo	 largo	 de	 los	 siguientes	 capítulos	 describiremos	 en	 detalle	 los	 contenidos		
específicos	 de	 cada	 interfaz	 en	 relación	 a	 cada	 tema.	 Ahora	 presentamos	 las	 interfaces	
comunes	de	la	asignatura,	Collec6onIF,	SetIF,	IteratorIF	y	ComparatorIF		
public	interface	CollectionIF<E>	{	
	
/**	
	*	Devuelve	el	número	de	elementos.																												
	*	@return	el	número	de	elementos.	
	*/	
public	int	size	();	
	
/**	
	*	Determina	si	la	colección	está	vacía.	
	*	@return	true	si	la	colección	está	vacía		
	*/	
public	boolean	isEmpty	();	
	
/**	
	*	Determina	si	un	elemento	está	contenido.	
	*	@param	el	elemento	a	comprobar.	
	*	@return	true,	si	está	contenido.		
/*		
public	boolean	contains	(E	e);		
	
/**	
	*	Elimina	todos	los	elementos.	
	*/	
public	void	clear	();	
	
/**	
	*	Devuelve	un	iterador	sobre	la	colección.	
	*	@return	un	iterador	sobre	la	colección.	
	*/	
public	IteratorIF<E>	iterator	();		
	
}	
1 7 4
3
1 7 4
false
true
1 7 4
false
1 7 4
true
3,
7,
1 7 4
1 7 4
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 15
Tipos	abstractos	de	datos	
Diseño	de	8pos	abstractos	de	datos	
Como	puede	apreciarse	en	el	diagrama	UML	de	clases	anterior,	cada	abstracción	de	datos	
se	representa	por	una	interfaz	que	especializa	las	capacidades	generales	de	una	colección	
abstracta.	 A	 lo	 largo	 de	 los	 siguientes	 capítulos	 describiremos	 en	 detalle	 los	 contenidos		
específicos	 de	 cada	 interfaz	 en	 relación	 a	 cada	 tema.	 Ahora	 presentamos	 las	 interfaces	
comunes	de	la	asignatura,	Collec6onIF,	SetIF,	IteratorIF	y	ComparatorIF		
public	interface	SetIF<E>		
	extends	CollectionIF<E>	{		
	
/**		
	*	Devuelve	la	unión	de	conjuntos.	
	*	@param	el	conjunto	a	unir.	
	*	@return	el	conjunto	tras	la	union.	
	*/		
public	SetIF<E>	union	(SetIF<E>	s);		
	
/**	
	*	Devuelve	la	intersección	de	conjuntos.	
	*	@param	el	conjunto	a	intersecar.	
	*	@return	el	conjunto	tras	la	intersección.	
	*/		
public	SetIF<E>	intersection	(SetIF<E>	s);		
	
**	
	*	Devuelve	la	diferencia	de	conjuntos.	
	*	@param	el	conjunto	a	diferenciar.	
	*	@return	el	conjunto	después	de	la	diferencia.	
	*/		
public	SetIF<E>	difference	(SetIF<E>	s);		
	
/**	
	*	Determina	si	un	conjunto	es	subconjunto.	
	*	@param	el	conjunto	a	comprobar.	
	*	@return	true	si	es	subconjunto	
	*/	
public	boolean	isSubset	(SetIF<E>	s);		
	
/**	
	*	Borra	todos	los	elementos	de	una	colección.	
	*	@param	la	colección.	
	*/	
public	void	removeAll	(CollectionIF<E>	c);		
1 7 4
2 4
1 7 42
1 7 4
2 4
4
1 7 4
2 4
2
1 7 4
2 4
false
4 7 4
2 4
2
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 16
Tipos	abstractos	de	datos	
Diseño	de	8pos	abstractos	de	datos	
Como	puede	apreciarse	en	el	diagrama	UML	de	clases	anterior,	cada	abstracción	de	datos	
se	representa	por	una	interfaz	que	especializa	las	capacidades	generales	de	una	colección	
abstracta.	 A	 lo	 largo	 de	 los	 siguientes	 capítulos	 describiremos	 en	 detalle	 los	 contenidos		
específicos	 de	 cada	 interfaz	 en	 relación	 a	 cada	 tema.	 Ahora	 presentamos	 las	 interfaces	
comunes	de	la	asignatura,	Collec6onIF,	SetIF,	IteratorIF	y	ComparatorIF		
public	interface	IteratorIF<T>	
{	
				/**	
					*	Devuelve	el	siguiente	elemento	de	la	iteracion.		
					*	@return	el	siguiente	elemento	de	la	iteracion.	
					*/	
				public	T	getNext	();	
					
					/**	
					*	Indica	si	hay	más	elemento	en	la	iteración.		
					*	@return	true	si	hay	más	elemento	en	la	iteración	
					*/	
				public	boolean	hasNext	();	
					
				/**	
					*	Restablece	el	iterador	para	volver	al	inicio.	
					*/	
				public	void	reset	();	
}					
					
1 7 42 1
1 7 42
true
1 7 42
false
1 7 42
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 17
Tipos	abstractos	de	datos	
Diseño	de	8pos	abstractos	de	datos	
Como	puede	apreciarse	en	el	diagrama	UML	de	clases	anterior,	cada	abstracción	de	datos	
se	representa	por	una	interfaz	que	especializa	las	capacidades	generales	de	una	colección	
abstracta.	 A	 lo	 largo	 de	 los	 siguientes	 capítulos	 describiremos	 en	 detalle	 los	 contenidos		
específicos	 de	 cada	 interfaz	 en	 relación	 a	 cada	 tema.	 Ahora	 presentamos	 las	 interfaces	
comunes	de	la	asignatura,	Collec6onIF,	SetIF,	IteratorIF	y	ComparatorIF		
public	interface	ComparatorIF<T>	
{	
				public	static	int	LT	=	-1;	
				public	static	int	EQ	=	0;	
				public	static	int	GT	=	1;	
					
				/**	
					*	Compara	dos	elementos	para	indicar	si	el	primero	es	
					*	menor,	igual	o	mayor	que	el	segundo	elemento.	
					*	@param	e1	el	primer		elemento.	
					*	@param	e2	el	segundo	elemento.	
					*	@return	el	orden	de	los	elementos.		
					*/	
				public	int	compare	(T	e1,	T	e2);	
					
				/**	
					*	Indica	si	un	elemento	es	menor	que	otro.		
					*	@param	e1	el	primer		elemento.	
					*	@param	e2	el	segundo	elemento.	
					*	@return	true		si	un	elemento	es	menor	que	otro.	
					*/	
				public	boolean	lt	(T	e1,	T	e2);	
				/**	
					*	Indica	si	un	elemento	es	igual	que	otro.		
					*	@param	e1	el	primer		elemento.	
					*	@param	e2	el	segundo	elemento.	
					*	@return	true		si	un	elemento	es	igual	que	otro.	
					*/	
				public	boolean	eq	(T	e1,	T	e2);	
					
				/**	
					*	Indica	si	un	elemento	es	mayor	que	otro.		
					*	@param	e1	el	primer		elemento.	
					*	@param	e2	el	segundo	elemento.	
					*	@return	true		si	un	elemento	es	mayor	que	otro.	
					*/	
				public	boolean	gt	(T	e1,	T	e2);	
}
Tipos	Abstractos	de	Datos	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 18
Bibliograga	
BibliograVa	
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
Javier	Vélez	Reyes	
jvelez@lsi.uned.es	
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	.	Grado	en	tecnologías	de	la	información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Parte	II	
Tipos	abstractos	de	
datos	lineales
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
5	Tipos	abstractos	de	
datos	lineales	
Listas
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 2
Índice	
Índice	
›  Introducción
›  Tipos abstractos de datos lineales
›  El tipo abstracto de datos lista
›  Interfaz del tipo abstracto de datos lista
›  Implementaciones del tipo abstracto de datos lista
›  Implementación dinámica
›  Implementación estática
›  Algoritmos sobre listas
›  Recorrido de los elementos de una lista
›  Búsqueda de un elemento sobre una lista
›  Ordenación de los elementos de una lista
›  Ejercicios
›  Bibliografía
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 3
Obje6vos	generales	
Obje8vos	
›  Comprender que son los tipos abstractos de datos lineales
›  Conocer la interfaz del tipo abstracto de datos Lista
›  Aprender a implementar el TAD Lista mediante la interfaz ListIF
›  En versión estática (con limitación explícita de capacidad máxima)
›  En versión dinámica (sin limitación explícita de capacidad máxima)
›  Conocer los principales problemas algorítmicos sobre listas
›  Recorrido de los elementos de una lista
›  Búsqueda de un elemento sobre una lista
›  Ordenación de los elementos de una lista
›  Practicar el diseño de funciones recursivas sobre listas
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 4
Introducción	
Tipos	abstractos	de	datos	lineales	
Los	6pos	abstractos	de	datos	lineales	representan	abstracciones	en	las	que	los	datos	son	
organizados	de	forma	secuencial.	A	con6nuación	se	muestran	los	diferentes	TADs	que	caen	
dentro	de	esta	categoría	y	que	se	diferencian,	esencialmente,	en	la	forma	en	que	ofrecen	
acceso	a	sus	datos	
Tipos abstractos
de datos lineales
I. Listas
II. Pilas
III. Colas
El tipo abstracto de datos Lista representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el principio,
que puede moverse recursivamente haciendo referencia a otras
sublistas
El tipo abstracto de dato Pila representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el principio
según la política de acceso último en entrar, primero en salir
El tipo abstracto de dato Cola representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el final y por el
principio respectivamente de acuerdo a la política de primero en
entrar, primero en salir
Tema 4
}
Tema 5
}
Tema 6
}
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 5
Introducción	
El	8po	abstracto	de	datos	lista	
Las	listas	son	abstracciones	de	datos	que	organizan	una	colección	de	elementos	de	manera	
secuencial,	donde	a	cada	elemento	le	sigue	un	único	elemento	siguiente.	La	definición	del	
6po	establece	un	modelo	posicional	donde	cada	elemento	se	iden6fica	por	un	índice	que	
permite	su	acceso	directo		
Una	lista	es	un	6po	abstractos	de	datos	que	organiza	una	colección	de	elementos	
de	 forma	 secuencial.	 Su	 definición	 permite	 acceder	 a	 sus	 elementos	 de	 forma	
directa	a	través	de	un	índice	posicional	
2	 3	 4	 5	 6	 7	 8	 9	
elementos	
Cada posición de la lista
guarda un valor de tipo
genérico
1	
posición	
Cada elemento dentro de la lista
adquiere un índice único que
identifica su posición y permite
accederlo de forma directa
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 6
Interfaz	del	6po	abstracto	de	datos	Lista	
La	interfaz	del	8po	abstracto	de	datos	Lista	ListIF	<T>	
public	interface	ListIF<T>	extends	CollectionIF<T>	
{	
				/**	
					*	Devuelve	el	elemento	en	la	posición	indicada.	
					*	@param	pos	La	posición	del	elemento.	
					*	@return	el	elemento	en	la	posición	indicada.	
					*/	
				public	T	get	(int	pos);	
					
				/**	
					*	Sobrescribe	el	elemento	en	la	posición	indicada.	
					*	@param	element	El	elemento	sustituto.	
					*	@param	pos	La	posición	que	ocupará	el	elemento.	
					*/	
				public	ListIF<T>	set	(int	pos,	T	element);	
					
				/**	
					*	Inserta	un	nuevo	elemento	a	la	lista.	
					*	@param	element	El	elemento	a	añadir.	
					*	@param	pos	La	posición	donde	debe	añadirse.	
					*/	
				public	void	insert	(T	element,	int	pos);	
									
				/**	
					*	Borra	el	elemento	en	la	posición	indicada.	
					*	@param	la	posición	del	elemento	a	borrar.	
					*/	
				public	void	remove	(int	pos);	
}	
El	interfaz	de	listas	que	u6lizaremos	a	lo	largo	
de	 este	 curso,	 ListIF	 esta	 compuesto	 por	 las	
operaciones	que	describimos	a	con6nuación	
1 7 44
2
1 7 4
32,
1 7 3
1 7 4
2
1 7
1 7 4
32,
7 3 41
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 7
Implementación	del	6po	abstracto	de	datos	Lista	
Implementación	del	8po	abstracto	de	datos	Lista	ListIF	<T>	
Existen	varias	estrategias	para	implementar	listas	que	respondan	al	interfaz	ListIF	anterior.	
En	 general,	 éstas	 se	 dividen	 en	 implementaciones	 dinámicas,	 que	 ar6culan	 listas	 de	
capacidad	indefinida	e	implementaciones	está6cas,	con	una	capacidad	máxima	limitada	y	
establecida	como	parámetro.	Aquí	presentamos	una	conveniente.	
Implementación	dinámica	basada	cadena	de	nodos	
Según	 esta	 estrategia	 de	 implementación,	 una	 lista	 está	 formada	 por	 un	 atributo	 que	
representa	 el	 elemento	 en	 la	 cabeza	 y	 otro	 que	 es	 una	 referencia	 a	 una	 lista	 que	
representa	el	resto	de	la	lista.	De	esta	manera	una	lista	es	una	colección	encadenada	de	
pares	(primero,	siguiente).	
1	 2	 3	 4	
Primero	y	resto	
Internamente cada objeto Lista contiene un
atributo para representar el elemento en
cabeza de lista y un atributo del tipo definido
ListIF que representa una referencia al resto de
elementos tras la cabeza
Lista	
La lista es una secuencia
de pares (primero, resto)
a c a b a d a e n u n p a r
fantasma
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 8
Algoritmos	sobre	listas	
Algoritmos	sobre	listas	
Estudiaremos	3	6pos	de	problemas	recurrentes	sobre	la	interfaz	de	listas	ListIF:	recorrido	
de	los	elementos	de	una	lista,	búsqueda	de	un	elemento	entre	los	elementos	de	una	lista	y	
ordenación	 ascendente	 de	 los	 elementos	 de	 una	 lista.	 La	 definición	 recursiva	 del	 6po	
condiciona	las	estrategias	algorítmicas	que	pueden	u6lizarse.	
Algoritmos
sobre listas
I. Recorrido
El recorrido de los elementos de una lista devuelve un iterador que permite
procesarlos secuencialmente según aparecen almacenados en la estructura.
Como la definición es recursiva solo el recorrido directo será estudiado. El
recorrido inverso es fácilmente implementable y se deja como ejercicio
II. Búsqueda
La búsqueda de un elemento sobre los elementos de una lista se realiza de
forma secuencial dada la definición recursiva del tipo lo que imprime un coste
lineal al algoritmo. Se estudiará el predicado de contención dejando como
ejercicio la búsqueda del mínimo y el máximo
III. Ordenación
La ordenación de los elementos de una lista, reorganiza sus elementos de
forma que se dispongan ascendentemente de acuerdo a cierto criterio de
comparación que se recibe como parámetro. En este capítulo estudiaremos
dos conocidos métodos de ordenación en listas: ordenación por inserción
(insert sort) y ordenación por mezcla (merge sort).La ordenación
descendente es similar y se deja como ejercicio.
Independenciadela
implementación
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 9
Algoritmos	sobre	listas	
Recorrido	de	los	elementos	de	una	lista	
Para	ar6cular	el	recorrido	secuencial	de	los	elementos	de	una	lista	debe	implementarse	el	
interfaz	IteratorIF.	Las	implementaciones	de	ListIF	anteriores	construyen	una	copia	de	la	
lista	como	manejador	para	garan6zar	que	la	iteración	no	modifique	el	estado	del	6po	
class	ListIterator<T>	implements	IteratorIF<T>		
{	
				private	ListIF<T>	handler	=	null;	
				private	int	pos;	
					
				/**	
					*	Constructor	para	ListIterator.	
					*	@param	handler	el	manejador	de	listas.	
					*/	
				public	ListIterator	(ListIF<T>	handler)	
				{	
								this.handler	=	handler;	
								this.pos	=	0;	
				}	
					
				/**	
					*	Devuelve	el	siguiente	elemento	de	la	iteracion.		
					*	@return	el	siguiente	elemento	de	la	iteracion.	
					*/	
				@Override	
				public	T	getNext	()		
				{	
								return	this.handler.get	(this.pos++);	
				}	
					
					
Se mantienen un manejadores de la lista y un
índice posicional que indica a la posición del
elemento en curso dentro de la iteración
Iteración	con	reset	
La operación de avance devuelve el elemento
apuntado por el índice posicional y lo actualiza
para marcar el recorrido recorrido. Para invocar
esta operación con seguridad hay que
asegurarse de que el manejador no apunta a la
lista vacía
Avance	
3	 4	1	 2	
getNext()
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 10
Algoritmos	sobre	listas	
Recorrido	de	los	elementos	de	una	lista	
Para	ar6cular	el	recorrido	secuencial	de	los	elementos	de	una	lista	debe	implementarse	el	
interfaz	IteratorIF.	Las	implementaciones	de	ListIF	anteriores	construyen	una	copia	de	la	
lista	como	manejador	para	garan6zar	que	la	iteración	no	modifique	el	estado	del	6po	
			/**	
					*	Devuelve	cierto	si	existen	mas	elementos	a	iterar.	
					*	@return	cierto	si	existen	mas	elementos	a	iterar.	
					*/	
				@Override	
				public	boolean	hasNext	()		
				{	
								return	this.pos	<	this.handler.size	();	
				}	
					
				/**	
					*	Restablece	el	iterador	para	volver	al	inicio.	
					*/	
				@Override	
				public	void	reset	()		
				{	
								this.pos	=	0;	
				}	
	
				@Override	
				public	int	hashCode	()	{	...	}	
	
				@Override	
				public	boolean	equals	(Object	o)	{	...	}	
	
				@Override	
				public	String	toString	()	{...}	
}					
Para saber si el iterador contiene más elementos y por
tanto puede volver a invocarse la operación de avance o
no, hay que preguntar si el índice posicional ha alcanzado
el final de la lista
Hay	siguiente	
Una vez que un iterador ha llegado a su fin sólo se puede
construir otro iterador, basta con volver a la posición inicial
el índice posicional
Reset	
3	 4	1	 2	
reset	()
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 11
Algoritmos	sobre	listas	
Búsqueda	de	un	elemento	sobre	una	lista	
La	búsqueda	de	un	dato	sobre	los	elementos	contenidos	en	una	lista	es	un	problema	de	
recorrido	secuencial	que	termina	cuando	se	encuentra	una	cabeza	que	corresponde	con	el	
dato	 buscado.	 En	 este	 sen6do	 puede	 aplicarse	 un	 algoritmo	 recursivo	 o	 aprovechar	 el	
iterador	anterior	para	resolverlo	itera6vamente	mediante	búsqueda	con	cen6nela	
Búsqueda	itera8va	con	cen8nela	
				/**	
					*	Devuelve	cierto	si	la	lista	contiene	el	elemento.	
					*	@param	element	El	elemento	buscado.	
					*	@return	cierto	si	la	lista	contiene	el	elemento.	
					*/	
				@Override	
				public	boolean	contains	(T	element)	
				{	
								IteratorIF<T>	listIt	=	this.iterator	();	
								boolean	found	=	false;	
								while	(!found	&&	listIt.hasNext	())	{	
												T	anElement	=	listIt.getNext	();	
												found	=	anElement.equals	(element);	
								}	
								return	found;	
				}	
					
En	la	búsqueda	con	cen6nela	se	itera	sobre	
la	 lista	 y	 se	 u6liza	 una	 guarda	 (cen6nela)	
para	 indicar	 el	 momento	 en	 que	 se	 ha	
encontrado	 el	 elemento	 y	 la	 búsqueda	
puede	parar	
Búsqueda	recursiva	
				/**	
					*	Devuelve	cierto	si	la	lista	contiene	el	elemento.	
					*	@param	element	El	elemento	buscado.	
					*	@return	cierto	si	la	lista	contiene	el	elemento.	
					*/	
				@Override	
				public	boolean	contains	(T	element)	
				{	
								this.contains	(element,	0);	
				}	
	
				private	boolean	contains	(T	e,	int	pos)	
								return	pos	>=	this.size	()	?		
																		false	:	
																		this.get	(pos).equals	(e)	||	contains	(e,	pos+1)	
				}	
En	la	búsqueda	recursiva	se	comprueba	si	la	
cabeza	 se	 corresponde	 con	 el	 elemento	
buscado.	 Si	 es	 así	 el	 algoritmo	 termina	
devolviendo	cierto	y	si	no,	se	recurre	sobre	
el	resto	de	la	lista	para	buscar	el	elemento
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 12
Algoritmos	sobre	listas	
Ordenación	de	los	elementos	de	una	lista	
Los	algoritmos	de	ordenación	que	pueden	aplicarse	sobre	listas,	son	rela6vamente	pocos,	
en	comparación	con	los	que	pueden	aplicarse	sobre	estructuras	de	indexación.	En	concreto	
nosotros	 discu6remos	 en	 este	 capítulo	 la	 ordenación	 por	 inserción	 y	 la	 ordenación	 por	
mezcla	
Si la lista es vacía se devuelve ésta. Sino, se
ordena el resto de la lista recursivamente y se
inserta en ella el primer elemento en la posición
adecuada según el criterio de orden
3	 2	5	 7	 3	 7	
5	
2	
Ordenación	por	inserción	 Ordenación	por	burbuja	
Se recorre en doble vuelta los elementos del
vector con 2 pivotes anidados i y j. El pivote i
avanza en 1..N y j en i+1..N. En cada iteración se
comparan los valores en i y j y si es necesario se
permutan
3	 2	5	 7	 3	 7	
5	
2	
Ordenación	por	mezcla	
Durante la primera fase, el algoritmo divide
recursivamente el problema en subproblemas de
la mitad de tamaño. Este proceso requiere
recorrer la lista y tiene un coste de complejidad
lineal
Una vez alcanzado elementos atómicos, la fase
de mezcla combina las soluciones ordenando
cada subproblema por combinación de sus
elementos. De esta forma, se obtiene, al final, el
array completamente ordenado
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 13
Ejercicios	
Ejercicios	
Dado	el	carácter	recursivo	de	la	definición	del	6po	abstracto	de	datos	ListIF,	la	mayoría	de	
algoritmos	sobre	listan	6enen	un	planteamiento	recursivo.	A	con6nuación	se	presentan	una	
colección	de	problemas	[picos	sobre	listas	para	que	se	resuelvan	de	esta	manera	
Diseñe	 una	 función	 recursiva	 que	
calcule	el	número	de	elementos	que	
con6ene	una	lista	
I. Longitud de una lista
Diseñe	 una	 función	 recursiva	 que	
compare	 lexicográficamente	 2	 listas	
de	caracteres.	
II. Comparar dos listas
Diseñe	 una	 función	 que	 dada	 una	
lista	determine	si	una	lista	es	sublista	
de	otra	dada	de	mayor	tamaño	
III. Sublista
Diseñe	 una	 función	 recursiva	
implemente	 la	 ordenación	 por	
inserción	
IV. Ordenar por inserción
Diseñe una función recursiva
implemente la ordenación por
mezcla
V. Ordenar por mezcla
Diseñe	 una	 función	 recursiva	 que	
devuelve	 la	 lista	 resultante	 de	
concatenar	dos	listas		
VI. Concatenar dos listas
Diseñe	 una	 función	 recursiva	 que	
devuelva	una	lista	con	los	elementos	
colocados	de	forma	inversa	a	otra	
VII. Lista inversa
Diseñe una función recursiva
implemente el método de
ordenación de la burbuja
VIII. Ordenar por burbuja
Diseñe	una	función	que	devuelva	una	
lista	donde	se	hayan	eliminado	todas	
las	apariciones	de	un	elemento	
IX. Borrar todos
Diseñe	 una	 función	 recursiva	 que	
devuelva	 una	 sublista	 prefijo	 que	
precede	a	un	elemento	dado	
X. Lista prefijo
Diseñe	 una	 función	 recursiva	 que	
devuelva	 la	 lista	 sufijo	 que	 sucede	 a	
un	elemento	dado	
XI. Lista sufijo
Diseñe	 una	 función	 recursiva	 que	
devuelva	 una	 lista	 con	 todos	 los	
elementos	mayores	a	uno	dado	
XII. Lista mayores
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 14
Ejercicios	
Ejercicios	
Dado	el	carácter	recursivo	de	la	definición	del	6po	abstracto	de	datos	ListIF,	la	mayoría	de	
algoritmos	sobre	listan	6enen	un	planteamiento	recursivo.	A	con6nuación	se	presentan	una	
colección	de	problemas	[picos	sobre	listas	para	que	se	resuelvan	de	esta	manera	
Diseñe	 una	 función	 recursiva	 que	
sume	1	a	todo	los	elementos	de	una	
lista	de	enteros	
XIII. Sumar 1
Diseñe	una	función	que	indique	si	dos	
elementos	 pertenecen	 a	 una	 lista	
dada	
XIV. Pertenecen 2
Diseñe	 una	 función	 que	 dadas	 dos	
listas	 que	 representan	 2	 conjuntos	
devuelva	la	lista	del	conjunto	unión	
XV. Unión de conjuntos
Diseñe	 una	 función	 que	 dadas	 dos	
listas	 devuelva	 los	 elementos	
comunes	a	ambas	
XVI. Intersección de listas
Diseñe	 una	 función	 que	 recibiendo		
un	conjunto	en	forma	de	lista	genere	
una	 lista	 de	 listas	 con	 las	 partes	 del	
conjunto	
XVII. Partes de un conjunto
Diseñe	 una	 función	 recursiva	 que	
dada	 una	 lista	 de	 ceros	 y	 unos	
devuelva	el	complemento	a	1	
XVIII. Complemento a 1
Diseñe	 una	 función	 que	 cuente	 el	
numero	 de	 veces	 que	 determinado	
elemento	aparece	en	una	lista	
XIX. Contador
Diseñe	 una	 función	 que	 genere	 una	
lista	 con	 el	 número	 de	 veces	 que	
aparece	cada	elemento	de	una	lista	
XX. Lista contador
Diseñe	 una	 función	 recursiva	 que	
calcule	 el	 producto	 escalar	 de	 dos	
vectores	expresados	en	listas	
XXI. Producto escalar
Dadas	 dos	 listas	 que	 representan	
números	 naturales,	 implemente	 el	
algoritmo	 de	 suma	 generando	 una	
lista	resultado	
XXII. Suma de listas
Diseñe	 una	 función	 que	 dada	 una	
lista	 de	 dígitos	 construya	 el	 número	
natural	que	representa	
XXIII. Convertir a número
Diseñe	 una	 función	 que	 dado	 un	
número	 genere	 una	 lista	 de	 dígitos	
que	lo	represente	
XXIV. Convertir a lista
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 15
Bibliogra^a	
BibliograMa	
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
Tipos	abstractos	de	datos	lineales.	Listas	
Javier Vélez Reyes jvelez@lsi.uned.es4 - 16
Bibliogra^a	
BibliograMa	
Bibliografía complementaria
Estructura de datos y algoritmos en java. A.
Drozdek. Thomsom. ISBN: 9706866116. 2007
Estructuras de datos con Java. J. Lewis, J.
Chase. Pearson – Addison Wesley. ISBN 13:
9788420541914
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
6	Tipos	abstractos	de	
datos	lineales	
Pilas
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 2
Índice	
Índice	
›  Introducción
›  Tipos abstractos de datos lineales
›  El tipo abstracto de datos Pila
›  Interfaz del tipo abstracto de datos Pila
›  Implementaciones del tipo abstracto de datos Pila
›  Implementación dinámica
›  Implementación estática
›  Implementación con Lista
›  Algoritmos sobre Pilas
›  Recorrido de los elementos de una Pila
›  Búsqueda de un elemento sobre una Pila
›  Problemas y ejercicios
›  Bibliografía
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 3
Obje6vos	generales	
Obje8vos	
›  Conocer la interfaz del tipo abstracto de datos Pila
›  Aprender a implementar el TAD Pila mediante la interfaz StackIF
›  En versión estática (con limitación explícita de capacidad máxima)
›  En versión dinámica (sin limitación explícita de capacidad máxima)
›  Utilizando una lista
›  Conocer los principales problemas algorítmicos sobre pilas
›  Recorrido de los elementos de una pila
›  Búsqueda de un elemento sobre una pila
›  Practicar el diseño de funciones recursivas sobre pilas
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 4
Introducción	
Tipos	abstractos	de	datos	lineales	
Los	6pos	abstractos	de	datos	lineales	representan	abstracciones	en	las	que	los	datos	son	
organizados	de	forma	secuencial.	A	con6nuación	se	muestran	los	diferentes	TADs	que	caen	
dentro	de	esta	categoría	y	que	se	diferencian,	esencialmente,	en	la	forma	en	que	se	ofrecen	
acceso	a	sus	datos	
Tipos abstractos
de datos lineales
I. Listas
II. Pilas
III. Colas
El tipo abstracto de datos Lista representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el principio,
que puede moverse recursivamente haciendo referencia a otras
sublistas
El tipo abstracto de dato Pila representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el principio
según la política de acceso último en entrar, primero en salir
El tipo abstracto de dato Cola representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el final y por el
principio respectivamente de acuerdo a la política de primero en
entrar, primero en salir
Tema 4
}
Tema 5
}
Tema 6
}
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 5
Introducción	
El	8po	abstracto	de	datos	Pila	
Las	pilas	son	abstracciones	de	datos	que	organizan	una	colección	de	elementos	de	manera	
secuencial,	donde	existe	un	único	punto	de	interés	llamado	cima	por	donde	se	realizan	las	
operaciones	de	acceso.	La	polí6ca	de	acceso	indica	que	el	úl6mo	elemento	en	entrar	en	una	
pila	es	el	primero	en	salir	de	ella	(Last	In	First	Out,	LIFO).		
Una	pila	es	un	6po	abstractos	de	datos	que	organiza	una	colección	de	elementos	
de	 forma	 secuencial.	 Las	 operaciones	 de	 acceso	 se	 realizan	 por	 un	 extremo	
llamado	cima	y	la	polí6ca	de	acceso	es	úl6mo	en	entrar	primero	en	salir	(LIFO)	
Cima	
Las operaciones de
inserción y
extracción se
realizan por un
extremo llamado
cima
Una pila puede imaginarse como una
estructura de datos que dispone los
mismos en secuencia uno encima de
otros de manera que siempre el último
elemento en apilarse es el único que
puede ser directamente accedido
Pila	
1	
2	
3	
4
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 6
Interfaz	del	6po	abstracto	de	datos	Pila	
La	interfaz	del	8po	abstracto	de	datos	Pila	StackIF	<T>	
public	interface	StackIF<T>	extends	CollectionIF<T>	{	
	
				/**	
					*	Devuelve	la	cima	de	la	pila.	
					*	@return	la	cima	de	la	pila.	
					*/	
				public	T	getTop	();	
					
				/**	
					*	Inserta	un	elemento	a	la	pida.	
					*	@param	element	El	elemento	a	ser	añadido.	
					*	@return	la	pila	incluyendo	el	elemento.	
					*/	
				public	StackIF<T>	push	(T	element);	
					
				/**	
					*	Extrae	de	la	pila	el	elemento	en	la	cima.	
					*	@return	la	pila	excluyendo	la	cabeza.	
					*/	
				public	StackIF<T>	pop	();	
																	
El	 interfaz	 de	 Pila	 que	 u6lizaremos	 a	 lo	 largo	 de	 este	
curso,	StackIF	está	compuesto	por	las	operaciones	que	
describimos	a	con6nuación	
cima	
Todas las operaciones de una pila se atacan
por la cima. Este método devuelve el elemento
en la cima sin extraerlo
2	
3	
1	1	
Insertar	
La operación push inserta un elemento encima
de la cima de manera que el elemento
insertado pasa a ser la nueva cima
2	
3	
1	
2	
3	
push	(1)	
Extraer	
La operación pop extrae el elemento en la cima
de la pila de manera que el elemento en la
cima pasa a ser el de siguiente en la pila
2	
3	
1	
2	
3	
pop	()
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 7
Implementación	del	6po	abstracto	de	datos	Pila	
Implementación	del	8po	abstracto	de	datos	Pila	StackIF	<T>	
Existen	varias	estrategias	para	implementar	pilas	que	responden	al	interfaz	StackIF	anterior.	
En	 general,	 éstas	 se	 dividen	 en	 implementaciones	 dinámicas,	 que	 ar6culan	 pilas	 de	
capacidad	indefinida	e	implementaciones	está6cas,	con	una	capacidad	máxima	limitada	y	
establecida	como	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	dinámica	basada	en	elemento	y	siguiente	
Según	 esta	 estrategia	 de	 implementación,	 una	 pila	 está	 formada	 por	 un	 atributo	 que	
representa	la	cima	y	otro	que	es	una	referencia	a	una	pila	y	representa	el	resto	de	la	pila.	
De	esta	manera	una	pila	es	una	colección	encadenada	de	pares	(elemento,	siguiente)	
1	 2	 3	 4	 -	 -	
Cima	y	siguiente	
Cada objeto Pila contiene un atributo para
representar el elemento en la cima de la pila y
un atributo del tipo definido StackIF que
representa una referencia al resto de
elementos debajo de la cima
Ul8mo,	elemento	fantasma	
Aunque en otras implementaciones el valor del
último objeto se aprovecha para incluir un
último elemento aquí el final se marca con un
objeto fantasma con ambos atributos a null.
Esto evita excepciones de puntero a null y
simplifica la algoritmia con la pila a un único
caso base isEmpty ()
Pila	
La pila es una secuencia
de pares (elemento,
siguiente) acabada en un
par fantasma
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 8
Implementación	del	6po	abstracto	de	datos	Pila	
Implementación	del	8po	abstracto	de	datos	Pila	StackIF	<T>	
Existen	varias	estrategias	para	implementar	pilas	que	responden	al	interfaz	StackIF	anterior.	
En	 general,	 éstas	 se	 dividen	 en	 implementaciones	 dinámicas,	 que	 ar6culan	 pilas	 de	
capacidad	indefinida	e	implementaciones	está6cas,	con	una	capacidad	máxima	limitada	y	
establecida	como	parámetro.	
Implementación	está8ca	basada	en	array	
Según	 esta	 estrategia	 de	 implementación,	 una	 pila	 está	 cons6tuida	 por	 un	 array	 de	
capacidad	limitada	y	especificada	mediante	un	parámetro	y	un	índice	que	apunta	a	la	
cima	de	la	pila.	La	pila	empieza	por	la	posición	0	y	avanza	hacia	posiciones	crecientes	
0	 0	0	 0	3	 7	2	 3	1	
cima	
Este índice apunta siempre
a l e l e m e n t o q u e s e
encuentra en la cima de la
pila. El índice comienza en
0 y llega hasta capacidad–1
para valores de la pila
Extraer	
Extraer mueve la cima de la pila
una posición hacia atrás con lo
que la posición anterior pasa a
ser la nueva cima. Cima == 0
indica una pila vacía luego esa
posición se desaprovecha
Insertar	
Las inserciones mueven la cima
una posición hacia adelante e
insertan el elemento. Si cima
llega a valer capacidad - 1 el
array está lleno y no se puede
insertar
Basura	
El resto de elementos del
array que no pertenecen a la
pila son basura, resultado
del trabajo con el tipo
Capacidad = 10
Pila	
La pila está formada por los
elementos que van desde la
posición 0 hasta cima
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 9
Implementación	del	6po	abstracto	de	datos	Pila	
Implementación	del	8po	abstracto	de	datos	Pila	StackIF	<T>	
Existen	varias	estrategias	para	implementar	pilas	que	responden	al	interfaz	StackIF	anterior.	
En	 general,	 éstas	 se	 dividen	 en	 implementaciones	 dinámicas,	 que	 ar6culan	 pilas	 de	
capacidad	indefinida	e	implementaciones	está6cas,	con	una	capacidad	máxima	limitada	y	
establecida	como	parámetro.		
Implementación	basada	en	lista	
Dado	que	las	implementaciones	de	pilas	que	hemos	visto	son	bastante	similares	a	las	de	
listas,	 es	 posible	 implementar	 una	 pila	 a	 par6r	 de	 una	 lista.	 El	 carácter	 	 está6co	 o	
dinámico	de	la	implementación	dependerá	del	6po	de	implementación	de	lista	u6lizada	
1	 2	 3	 4	 5	 6	 7	 8	 9	
Primero	es	cima	
El primer elemento
de una lista se
corresponde con la
cima de la pila
Resto	es	resto	de	pila	
El resto de elementos de la lista
corresponde con la subpila que hay
debajo de la cima
Pila	
La pila se implementa a partir de cualquier implementación del
TAD Lista con interfaz ListIF. La operación de insertar se
implementa con la inserción en la lista y la de extracción con la
operación de obtener resto de la lista
ListIF
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 10
Algoritmos	sobre	pilas	
Algoritmos	sobre	pilas	
A	diferencia	de	lo	que	ocurría	en	el	caso	de	las	listas	donde	estudiamos	que	la	ordenación	
era	uno	de	los	problemas	recurrentes,	en	el	caso	de	las	pilas	se	considera		que	tal	6po	de	
manipulaciones	no	son	de	interés	ya	que	irían	en	contra	de	la	esencia	organiza6va	del	6po	–	
mantener	a	los	elementos	dispuestos	en	el	orden	de	llegada	de	acuerdo	a	una	polí6ca	LIFO.	
Por	 ello,	 en	 esta	 sección	 nos	 centraremos	 en	 discu6r	 el	 problema	 del	 recorrido	 de	 los	
elementos	de	una	pila		y	la	búsqueda	de	un	elemento	dentro	de	una	pila.	
Algoritmos
sobre pilas
I. Recorrido
El recorrido de los elementos de una pila devuelve un iterador que permite
acceder secuencialmente a los mismos según aparecen almacenados en la
estructura, en sentido desde la cima hasta la base de la pila. El recorrido en
sentido contrario es fácilmente implementable y se deja como ejercicio
II. Búsqueda
La búsqueda de un elemento sobre los elementos de una pila se realiza de
forma secuencial dada la definición del tipo lo que imprime un coste lineal al
algoritmo. Si esta operación no fuese una operación interna del tipo dicha
búsqueda sería destructiva o requeriría utilizar un iterador (con copia) o
reconstruir la estructura tras el algoritmo. La búsqueda como operación
interna permite implementar el algoritmo no destructivamente sobre la
estructura interna.
Independenciadela
implementación
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 11
Algoritmos	sobre	pilas	
Recorrido	de	los	elementos	de	una	pila	
Para	ar6cular	el	recorrido	secuencial	de	los	elementos	de	una	pila	debe	implementarse	el	
interfaz	IteratorIF.	Las	implementaciones	de	StackIF	anteriores	construyen	una	copia	de	la	
pila	como	manejador	para	garan6zar	que	la	iteración	no	modifique	el	estado	del	6po	
class	StackIterator<T>	implements	IteratorIF<T>		
{	
				private	StackIF<T>	handler;	
				private	StackIF<T>	restart;	
					
				/**	
					*	Constructor	para	StackIterator.	
					*	@param	handler	el	manejador	de	pilas.	
					*/	
				public	StackIterator	(StackIF<T>	handler)	
				{	
								this.handler	=	handler;	
								this.restart	=	new	StackDynamic<T>	(handler);	
				}	
					
				/**	
					*	Devuelve	el	siguiente	elemento	de	la	iteracion.		
					*	@return	el	siguiente	elemento	de	la	iteracion.	
					*/	
				@Override	
				public	T	getNext	()		
				{	
								T	top	=	handler.getTop	();	
								handler.pop	();	
								return	top;	
				}	
Se mantienen 2 manejadores constantemente,
uno para articular el recorrido de la pila. El otro
siempre apunta a la cima de la pila y se utiliza
para implementar la operación de reset del
iterador
Iteración	con	reset	
La operación de avance devuelve el elemento en
cima de la pila y actualiza el manejador de
recorrido extrayendo la cima. Para invocar esta
operación con seguridad hay que asegurarse de
que el manejador no apunta a la cola vacía…
Avance	
2	
1	
4	
3	
handler	
getNext()	
restart
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 12
Algoritmos	sobre	pilas	
Recorrido	de	los	elementos	de	una	pila	
Para	ar6cular	el	recorrido	secuencial	de	los	elementos	de	una	pila	debe	implementarse	el	
interfaz	IteratorIF.	Las	implementaciones	de	StackIF	anteriores	construyen	una	copia	de	la	
pila	como	manejador	para	garan6zar	que	la	iteración	no	modifique	el	estado	del	6po	
				/**	
					*	Devuelve	cierto	si	existen	mas	elementos	a	iterar.	
					*	@return	cierto	si	existen	mas	elementos	a	iterar.	
					*/	
				@Override	
				public	boolean	hasNext	()		
				{	
								return	!handler.isEmpty	();	
				}	
					
				/**	
					*	Restablece	el	iterador	para	volver	al	inicio	
					*/	
				@Override		
				public	void	reset	()		
				{	
								handler	=	new	StackDynamic<T>	(restart);	
				}	
	
				@Override	
				public	int	hashCode	()	{	...	}	
	
				@Override	
				public	boolean	equals	(Object	o)	{	...	}	
	
				@Override	
				public	String	toString	()	{...}	
}					
Para saber si el iterador contiene más elementos y por
tanto puede volver a invocarse la operación de avance o
no, hay que preguntar si el manejador ha alcanzado el final
de la pila
Hay	siguiente	
Una vez que un iterador ha llegado a su fin sólo se puede
construir otro iterador, o resetear este a su valor inicial. En
este caso sin embargo, la operación de reset requiere una
copia con lo que el coste es idéntico al de construir un
nuevo iterador.
Reset	
2	
1	
4	
3	
handler	
reset	()	
restart	handler
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 13
Algoritmos	sobre	pilas	
Búsqueda	de	un	elemento	sobre	una	pila	
La	búsqueda	de	un	dato	sobre	los	elementos	contenidos	en	una	pila	es	un	problema	de	
recorrido	secuencial	que	termina	cuando	se	encuentra	una	cima	que	corresponde	con	el	
dato	buscado.	El	problema	es	que	la	búsqueda	sobre	el	6po	es	destruc6va	a	no	ser	que	se	
aplique	sobre	la	implementación	o	se	u6lice	un	iterador	
Búsqueda	itera8va	con	cen8nela	
				/**	
					*	Devuelve	cierto	si	la	pila	contiene	el	elemento.	
					*	@param	element	El	elemento	buscado.	
					*	@return	cierto	si	la	pila	contiene	el	elemento.	
					*/	
				@Override	
				public	boolean	contains	(T	element)	
				{	
								IteratorIF<T>	stackIt	=	this.getIterator	();	
								boolean	found	=	false;	
								while	(!found	&&	stackIt.hasNext	())	{	
												T	anElement	=	stackIt.getNext	();	
												found	=	anElement.equals	(element);	
								}	
								return	found;	
				}	
					
En	la	búsqueda	con	cen6nela	se	itera	sobre	
la	pila	y	se	u6liza	una	guarda	(cen6nela)	para	
indicar	el	momento	en	que	se	ha	encontrado	
el	elemento	y	la	búsqueda	puede	parar	
Búsqueda	recursiva	
				/**	
					*	Devuelve	cierto	si	la	lista	contiene	el	elemento.	
					*	@param	element	El	elemento	buscado.	
					*	@return	cierto	si	la	lista	contiene	el	elemento.	
					*/	
				@Override	
				public	boolean	contains	(T	element)	
				{	
								if	(isEmpty	())	return	false;	
								return	this.element.equals	(element)	||	
															next.contains	(element);	
				}	
En	la	búsqueda	recursiva	se	comprueba	si	la	
cabeza	 se	 corresponde	 con	 el	 elemento	
buscado.	 Si	 es	 así	 el	 algoritmo	 termina	
devolviendo	cierto	y	si	no,	se	recurre	sobre	
el	resto	de	la	pila	para	buscar	el	elemento
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 14
Problemas	y	ejercicios	
Ejercicios	
Dado	el	carácter	destruc6vo	de	las	operaciones	sobre	pilas	–	para	avanzar	en	una	pila	es	
necesario	extraer	su	cima	con	pop	–	la	realización	de	muchos	de	sus	algoritmos	requiere	de	
un	 proceso	 de	 protección	 consistente	 en	 hacer	 una	 copia	 de	 la	 misma.	 Ignorando	 el	
problema	de	destrucción	resuelva	los	siguientes	problemas	
Diseñe	 una	 función	 que	 calcule	 el	
número	 de	 elementos	 que	 con6ene	
una	pila	
I. Longitud de una pila
Devolver	una	lista	con	los	elementos	
de	 una	 pila	 según	 aparecen	 en	 ésta	
desde	la	cima	hasta	la	base	
II. Pasar a lista
Diseñe	 una	 función	 que	 dada	 una	
lista	determine	si	ésta	está	contenida	
en	una	pila	como	subpila	
III. Subpila
Diseñe	 una	 función	 que	 devuelva	 el	
elemento	base	de	una	pila	
IV. Elemento base
Diseñe	 una	 función	 que	 inserte	 un	
dato	 como	 elemento	 en	 la	 base	 de	
una	pila	
V. Insertar en la base
Diseñe	 una	 función	 recursiva	 que	
devuelva	 la	 pila	 resultante	 de	
concatenar	dos	pilas	
VI. Concatenar dos pilas
Diseñe	 una	 función	 recursiva	 que	
devuelva	 una	 pila	 con	 los	 elementos	
colocados	de	forma	inversa	a	otra	
VII. Pila inversa
Diseñe	una	función	que	devuelva	una	
pila	que	elimine	la	primera	aparición	
de	un	elemento		
VIII. Borrado de un elemento
Diseñe	una	función	que	devuelva	una	
pila	donde	se	hayan	eliminado	todas	
las	apariciones	de	un	elemento	
IX. Borrar todos
Diseñe	una	función	que	devuelva	una	
pila	con	los	elementos		que	preceden	
a	 (están	 encima	 de)	 un	 elemento	
dado	
X. Pila prefijo
Diseñe	 una	 función	 que	 devuelva	 la	
pila	con	los	elementos	que	suceden	a	
(están	debajo	de)	un	elemento	dado	
XI. Pila sufijo
Diseñe	 una	 función	 recursiva	 que	
devuelva	 una	 pila	 con	 todos	 los	
elementos	mayores	a	uno	dado	
XII. Pila mayores
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 15
Problemas	y	ejercicios	
Problemas	
Las	pilas	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	problemas	de	
cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	 ejemplos	 de	
problemas	que	se	resuelven	con	el	uso	de	pilas.	
El	juego,	en	su	forma	más	tradicional,	consiste	en	
tres	varillas	ver6cales.	En	una	de	las	varillas	se	apila	
un	número	n	de	discos.	Los	discos	se	apilan	sobre	
una	 varilla	 en	 tamaño	 decreciente.	 No	 hay	 dos	
discos	 iguales,	 y	 todos	 ellos	 están	 apilados	 de	
mayor	 a	 menor	 radio	 en	 una	 de	 las	 varillas,	
quedando	las	otras	dos	varillas	vacantes.		
Las torres de Hanoi
1.  Sólo	se	puede	mover	un	disco	cada	vez.	
2.  Un	disco	de	mayor	tamaño	no	puede	descansar	sobre	uno	más	pequeño	que	él	mismo.	
3.  Sólo	puedes	desplazar	el	disco	que	se	encuentre	arriba	en	cada	varilla.	
El	juego	consiste	en	pasar	todos	los	discos	de	la	varilla	ocupada	a	una	de	las	otras	varillas	
vacantes.	Para	realizar	este	obje6vo,	es	necesario	seguir	tres	simples	reglas:
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 16
Problemas	y	ejercicios	
Problemas	
Las	pilas	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	problemas	de	
cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	 ejemplos	 de	
problemas	que	se	resuelven	con	el	uso	de	pilas.	
La	 finalidad	 del	 Solitario	 Carta	 blanca	 es	
mover	 todas	 las	 cartas	 desde	 la	 zona	 del	
tablero	 a	 las	 casillas	 de	 palo:	 los	 cuatro	
recuadros	 situados	 en	 la	 parte	 superior	
derecha	del	tablero.	Para	ganar,	el	jugador	
6ene	 que	 hacer	 cuatro	 montones	 de	
cartas	en	las	casillas,	uno	por	cada	palo,	y	
amontonarlas	en	orden	ascendente	desde	
el	AS	hasta	el	REY.	Puedes	mover	las	cartas	
de	 una	 columna	 a	 otra	 ordenando	 las	
cartas	de	mayor	a	menor	y	alternando	los	
La carta blanca
colores	de	los	palos,	así	como	u6lizar	las	casillas	libres	para	apartar	cartas	de	las	columnas	y	
así	acceder	a	la	carta	que	hay	debajo.	La	par6da	finaliza	cuando	el	jugador	ha	movido	todas	
las	cartas	a	las	casillas	de	palo	o	cuando	ya	no	puede	realizar	ningún	movimiento	más.	Se	dice	
que	todas	las	par6das	de	Carta	blanca	pueden	ganarse.
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 17
Problemas	y	ejercicios	
Problemas	
Las	pilas	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	problemas	de	
cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	 ejemplos	 de	
problemas	que	se	resuelven	con	el	uso	de	pilas.	
Aunque	actualmente	las	calculadores	permiten	
operar	 con	 expresiones	 en	 notación	 infija,	
tradicionalmente	 ha	 sido	 frecuente	 encontrar	
máquinas	 que	 requerían	 introducir	 las	
expresiones	en	notación	posdija.	Esto	facilita	la	
forma	de	calculo	y	evita	el	uso	de	paren6zación	
para	desambiguar.	De	esta	manera,	2	+	3	*	5	se	
expresa	en	notación	posdija	como	2	3	+	5	*	y	
debe	interpretarse	como		que	a	los	operandos…	
Calculadora en notación postfija
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 18
Bibliograia	
BibliograTa	
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
Tipos	abstractos	de	datos	lineales.	Pilas	
Javier Vélez Reyes jvelez@lsi.uned.es5 - 19
Bibliograia	
BibliograTa	
Bibliografía complementaria
Estructura de datos y algoritmos en java. A.
Drozdek. Thomsom. ISBN: 9706866116. 2007
Estructuras de datos con Java. J. Lewis, J.
Chase. Pearson – Addison Wesley. ISBN 13:
9788420541914
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
7	Tipos	abstractos	de	
datos	lineales	
Colas
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 2
Índice	
Índice	
›  Introducción
›  Tipos abstractos de datos lineales
›  El tipo abstracto de datos Cola
›  Interfaz del tipo abstracto de datos Cola
›  Implementaciones del tipo abstracto de datos Cola
›  Implementación dinámica
›  Implementación estática
›  Implementación con Lista
›  Algoritmos sobre Colas
›  Recorrido de los elementos de una Cola
›  Búsqueda de un elemento sobre una Cola
›  Problemas y ejercicios
›  Bibliografía
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 3
Obje6vos	generales	
Obje8vos	
›  Conocer la interfaz del tipo abstracto de datos Cola
›  Aprender a implementar el TAD Cola mediante la interfaz QueueIF
›  En versión estática (con limitación explícita de capacidad máxima)
›  En versión dinámica (sin limitación explícita de capacidad máxima)
›  Utilizando una lista
›  Conocer los principales problemas algorítmicos sobre colas
›  Recorrido de los elementos de una cola
›  Búsqueda de un elemento sobre una cola
›  Practicar el diseño de funciones recursivas sobre cola
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 4
Introducción	
Tipos	abstractos	de	datos	lineales	
Los	6pos	abstractos	de	datos	lineales	representan	abstracciones	en	las	que	los	datos	son	
organizados	de	forma	secuencial.	A	con6nuación	se	muestran	los	diferentes	TADs	que	caen	
dentro	de	esta	categoría	y	que	se	diferencian,	esencialmente,	en	la	forma	en	que	se	ofrecen	
acceso	a	sus	datos	
Tipos abstractos
de datos lineales
I. Listas
II. Pilas
III. Colas
El tipo abstracto de datos Lista representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el principio,
que puede moverse recursivamente haciendo referencia a otras
sublistas
El tipo abstracto de dato Pila representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el principio
según la política de acceso último en entrar, primero en salir
El tipo abstracto de dato Cola representa una estructuras de datos
donde los elementos se disponen de forma secuencial y las
operaciones de inserción y extracción se aplican por el final y por el
principio respectivamente de acuerdo a la política de primero en
entrar, primero en salir
Tema 4
}
Tema 5
}
Tema 6
}
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 5
Introducción	
El	8po	abstracto	de	datos	Cola	
Las	colas	son	abstracciones	de	datos	que	organizan	una	colección	de	elementos	de	manera	
secuencial,	donde	existen	dos	puntos	de	interés	llamados	comienzo	y	final.	Por	el	comienzo	
se	 realizan	 las	 operaciones	 de	 extracción	 mientras	 que	 por	 el	 final	 se	 realizan	 las	
inserciones.	Según	esto,	la	polí6ca	de	acceso	prescribe	que	el	primer	elemento	en	entrar	en	
una	cola	es	el	primero	en	salir	de	ella	(First	In	First	Out,	FIFO).		
Una	cola	es	un	6po	abstractos	de	datos	que	organiza	una	colección	de	elementos	
de	forma	secuencial.	Las	operaciones	de	extracción	se	realizan	por	el	principio	y	
las	de	inserción	por	el	final	de	acuerdo	a	la	polí6ca	de	acceso	FIFO	que	prescribe	
que	el	primero	en	entrar	es	el	primero	en	salir	
Primero	
El primero marca el
siguiente elemento a
extraer. Tras una
extracción, primero
avanza al siguiente en
la cola
1	 2	 3	 4	 5	 6	 7	 8	 9	
Ul8mo	
El último marca el
último elemento que se
ha insertado. Tras una
inserción, último apunta
al elemento insertado
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 6
Interfaz	del	6po	abstracto	de	datos	Cola	
La	interfaz	del	8po	abstracto	de	datos	Cola	QueueIF	<T>	
public	interface	QueueIF<T>	extends	CollectionIF<T>	
{	
				/**	
					*	Devuelve	la	cabeza	de	la	cola.	
					*	@return	la	cabeza	de	la	cola.	
					*/	
				public	T	getFirst	();	
									
				/**	
					*	Inserta	un	nuevo	elemento	a	la	cola.	
					*	@param	element	El	elemento	a	añadir.	
					*	@return	la	cola	incluyendo	el	elemento.	
					*/	
				public	QueueIF<T>	enqueue	(T	element);	
					
				/**	
					*	Borra	la	cabeza	de	la	cola.	
					*	la	cola	excluyendo	la	cabeza.	
					*/	
				public	QueueIF<T>	dequeue	();	
									
					
					
El	interfaz	de	Cola	que	u6lizaremos	a	lo	largo	de	este	
curso,	QueueIF	está	compuesto	por	las	operaciones	que	
describimos	a	con6nuación	
primero	
Devuelve el elemento que se encuentra en la
cabeza de la cola sin extraerlo de la misma.
Esta es una operación consultora
Insertar	
La operación add inserta un elemento detrás
del último elemento de la cola de manera que
este pasa a ser el nuevo último
borrar	
La operación remove extrae el elemento que
se encuentra en la cabeza de la cola dejando
al siguiente a éste como nueva cabeza
1 2 31	
1 2 3 4
1 2 3 4
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 7
Implementación	del	6po	abstracto	de	datos	Cola	
Implementación	del	8po	abstracto	de	datos	Cola	QueueIF	<T>	
Existen	 varias	 estrategias	 para	 implementar	 colas	 que	 responden	 al	 interfaz	 QueueIF	
anterior.	En	general,	éstas	se	dividen	en	implementaciones	dinámicas,	que	ar6culan	colas	
de	capacidad	indefinida	e	implementaciones	está6cas,	con	una	capacidad	máxima	limitada	
y	establecida	como	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	dinámica	basada	en	primero	y	úl8mo	
Según	 esta	 estrategia	 de	 implementación,	 una	 cola	 está	 formada	 por	 una	 cadena	 de	
nodos	enlazados	con	referencias	al	siguiente	y	dos	referencias	que	apuntan	al	primer	y	
úl6mo	 elemento	 de	 la	 cola.	 La	 desventaja	 de	 esta	 implementación	 es	 que	 hay	 que	
separar	la	abstracción	de	la	cadena	de	nodos	
1	 2	 3	 4	 -	
primero	
La referencia al primero se
mantiene para saber que
elemento extraer en cada
paso
Datos	 Los elementos de la cola se representan
mediante una estructura de nodos
encadenados por referencias al siguiente
ul8mo	
La referencia al último se
mantiene para saber detrás
de quién se debe hacer la
siguiente inserción
cola
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 8
Implementación	del	6po	abstracto	de	datos	Cola	
Implementación	del	8po	abstracto	de	datos	Cola	QueueIF	<T>	
Existen	 varias	 estrategias	 para	 implementar	 colas	 que	 responden	 al	 interfaz	 QueueIF	
anterior.	En	general,	éstas	se	dividen	en	implementaciones	dinámicas,	que	ar6culan	colas	
de	capacidad	indefinida	e	implementaciones	está6cas,	con	una	capacidad	máxima	limitada	
y	establecida	como	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	está8ca	basada	en	array	circular	
Según	 esta	 estrategia	 de	 implementación,	 una	 cola	 se	 almacena	 en	 un	 array	 de	
capacidad	limitada	accedido	circularmente	mediante	dos	índices	en	aritmé6ca	modular	
que	apuntan	al	primer	y	ul6mo	elemento	
2	 3	0	 1	3	 7	2	 3	4	 5	
primero	
El índice primero apunta siempre al
elemento en cabeza de la cola. Cuando
éste llega al índice máximo del array
continua modularmente por 0
Insertar	
Las inserciones se realizan en la
posición último y avanzan el
índice último una posición en
aritmética modular
Capacidad = 10
úl8mo	
El índice último apunta siempre al primer
hueco libre tras el último elemento de la
cola. . Cuando éste llega al índice máximo
del array continua modularmente por 0
extraer	
Las extracciones avanzan el
índice primero una posición en
aritmética modular
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 9
Implementación	del	6po	abstracto	de	datos	Cola	
Implementación	del	8po	abstracto	de	datos	Cola	QueueIF	<T>	
Existen	 varias	 estrategias	 para	 implementar	 colas	 que	 responden	 al	 interfaz	 QueueIF	
anterior.	En	general,	éstas	se	dividen	en	implementaciones	dinámicas,	que	ar6culan	colas	
de	capacidad	indefinida	e	implementaciones	está6cas,	con	una	capacidad	máxima	limitada	
y	establecida	como	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	basada	en	lista	
Dado	que	la	implementación	dinámica	de	colas	que	hemos	visto	es	bastante	similar	a	la	
de	listas,	es	posible	implementar	una	cola	a	par6r	de	una	lista.	El	carácter	 	está6co	o	
dinámico	de	la	implementación	dependerá	del	6po	de	implementación	de	lista	u6lizada	
1	 2	 3	 4	 5	 6	 7	 8	 9	
primero	
La referencia al primero se
mantiene para saber que
elemento extraer encada
paso
ul8mo	
La referencia al último se
mantiene para garantizar
una inserción en coste
constante
ListIF	
cola
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 10
Algoritmos	sobre	colas	
Algoritmos	sobre	colas	
A	diferencia	de	lo	que	ocurría	en	el	caso	de	las	listas	donde	estudiamos	que	la	ordenación	
era	uno	de	los	problemas	recurrentes,	en	el	caso	de	las	colas	se	considera		que	tal	6po	de	
manipulaciones	no	son	de	interés	ya	que	irían	en	contra	de	la	esencia	organiza6va	del	6po	–	
mantener	a	los	elementos	dispuestos	en	el	orden	de	llegada	de	acuerdo	a	una	polí6ca	FIFO.	
Por	 ello,	 en	 esta	 sección	 nos	 centraremos	 en	 discu6r	 el	 problema	 del	 recorrido	 de	 los	
elementos	de	una	cola	y	la	búsqueda	de	un	elemento	dentro	de	una	cola.	
Algoritmos
sobre colas
I. Recorrido
El recorrido de los elementos de una cola devuelve un iterador que permite
acceder secuencialmente a los mismos según aparecen almacenados en la
estructura, desde el primero hasta el último de la cola. El recorrido en sentido
contrario es fácilmente implementable y se deja como ejercicio
II. Búsqueda
La búsqueda de un elemento sobre los elementos de una cola se realiza de
forma secuencial dada la definición del tipo lo que imprime un coste lineal al
algoritmo. El problema fundamental en este tipo de algoritmos es que dicha
búsqueda es destructiva y requiere o utilizar un iterador (con copia) o
reconstruir la estructura tras el algoritmo
Independenciadela
implementación
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 11
Algoritmos	sobre	colas	
Recorrido	de	los	elementos	de	una	cola	
Para	ar6cular	el	recorrido	secuencial	de	los	elementos	de	una	cola	debe	implementarse	el	
interfaz	IteratorIF.	Las	implementaciones	de	QueueIF	anteriores	construyen	una	copia	de	la	
cola	como	manejador	para	garan6zar	que	la	iteración	no	modifique	el	estado	del	6po	
class	QueueIterator<T>	implements	IteratorIF<T>		
{	
				private	QueueIF<T>	handler;	
				private	QueueIF<T>	restart;	
					
				/**	
					*	Constructor	para	QueueIterator.	
					*	@param	handler	el	manejador	de	colas.	
					*/	
				public	QueueIterator	(QueueIF<T>	handler)	
				{	
								this.handler	=	handler;	
								this.restart	=	new	QueueDynamic<T>	(handler);	
				}	
					
				/**	
					*	Devuelve	el	siguiente	elemento	de	la	iteracion.		
					*	@return	el	siguiente	elemento	de	la	iteracion.	
					*/	
				@Override	
				public	T	getNext	()		
				{	
								T	element	=	handler.getFirst	();	
								handler.remove	();	
								return	element;	
				}	
Se mantienen 2 manejadores constantemente,
uno para articular el recorrido de la cola. El otro
siempre apunta a la cabeza de la cola y se utiliza
para implementar la operación de reset del
iterador
Iteración	con	reset	
La operación de avance devuelve el elemento en
cabeza de la cola y actualiza el manejador de
recorrido extrayendo la cima. Para invocar esta
operación con seguridad hay que asegurarse de
que el manejador no apunta a la cola vacía…
Avance	
3	 4	1	 2	
handler	 getNext()	
restart
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 12
Algoritmos	sobre	colas	
Recorrido	de	los	elementos	de	una	cola	
Para	ar6cular	el	recorrido	secuencial	de	los	elementos	de	una	cola	debe	implementarse	el	
interfaz	IteratorIF.	Las	implementaciones	de	QueueIF	anteriores	construyen	una	copia	de	la	
cola	como	manejador	para	garan6zar	que	la	iteración	no	modifique	el	estado	del	6po	
/**	
					*	Devuelve	cierto	si	existen	mas	elementos	a	iterar.	
					*	@return	cierto	si	existen	mas	elementos	a	iterar.	
					*/	
				@Override	
				public	boolean	hasNext	()		
				{	
								return	!handler.isEmpty	();	
				}	
					
				/**	
					*	Restablece	el	iterador	para	volver	iterar.	
					*/	
				@Override		
				public	void	reset	()		
				{	
								handler	=	new	QueueDynamic<T>	(restart);	
				}	
}	
Para saber si el iterador contiene más elementos y por
tanto puede volver a invocarse la operación de avance o
no, hay que preguntar si el manejador ha alcanzado el final
de la cola
Hay	siguiente	
Una vez que un iterador ha llegado a su fin sólo se puede
construir otro iterador, o resetear éste a su valor inicial. En
este caso sin embargo, la operación de reset requiere una
copia con lo que el coste es idéntico al de construir un
nuevo iterador.
Reset	
3	 4	1	 2	
handler	
reset()	
restart	
handler
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 13
Algoritmos	sobre	colas	
Búsqueda	de	un	elemento	sobre	una	cola	
La	búsqueda	de	un	dato	sobre	los	elementos	contenidos	en	una	cola	es	un	problema	de	
recorrido	secuencial	que	termina	cuando	se	encuentra	una	cabeza	que	corresponde	con	el	
dato	buscado.	Dado	que	el	6po	no	6ene	una	definición	recursiva,	el	problema	de	búsqueda	
no	 se	 presta	 a	 este	 6po	 de	 resolución	 algorítmica.	 A	 con6nuación	 presentamos	 dos	
versiones	de	la	búsqueda	itera6va	con	cen6nela	que	aprovechan	la	estructura	interna	de	la	
implementación	del	6po	
Búsqueda	en	QueueDynamic	
				@Override	
				public	boolean	contains	(T	element){	
								boolean	found	=	false;	
								Node<T>	node	=	first;	
								while	(!found	&&	node	!=	null)	{	
												found	=	node.getElement	().equals	(element);	
												node		=	node.getNext	();	
								}	
								return	found;	
				}	
	
Es	 esta	 implementación	 se	 realiza	 una	
búsqueda	 con	 cen6nela	 sobre	 la	 estructura	
de	nodos	enlazados	que	implementar	el	6po	
cola	
Búsqueda	en	QueueSta8c	
				@Override	
				public	boolean	contains	(T	element)	
				{	
								boolean	found	=	false;	
								int	index	=	first;	
								while	(!found	&&	Math.abs	(last	-	index)	>	0)	{	
												found	=	elements	[index].equals	(element);	
												index	=	next	(index);	
								}	
								return	found;	
				}	
En	la	implementación	está6ca	los	datos	son	
almacenados	sobre	una	estructura	vectorial	
que	debe	ser	recorrida	circularmente	desde	
el	 primero	 hasta	 el	 úl6mo	 elemento,	 si	 el	
cen6nela	no	lo	impide
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 14
Problemas	y	ejercicios	
Ejercicios	
Dado	el	carácter	destruc6vo	de	las	operaciones	sobre	colas	–	para	avanzar	en	una	cola	es	
necesario	 extraer	 su	 cabeza	 con	 invocando	 a	 remove	 –	 la	 realización	 de	 muchos	 de	 sus	
algoritmos	 requiere	 de	 un	 proceso	 de	 protección	 consistente	 en	 hacer	 una	 copia	 de	 la	
misma.	Ignorando	el	problema	de	destrucción	resuelva	los	siguientes	problemas	
Diseñe	 una	 función	 que	 calcule	 el	
número	 de	 elementos	 que	 con6ene	
una	cola	
I. Longitud de una cola
Devolver	una	lista	con	los	elementos	
de	 una	 cola	 según	 aparecen	 en	 ésta	
desde	el	primero	al	úl6mo	
II. Pasar a lista
Diseñe	una	función	que	dada	una	cola	
determine	si	es	subcola	de	otra	dada	
de	mayor	tamaño	
III. Subcola
Función	 que	 extrae	 los	 números	
pares	de	una	cola	de	enteros.	Repita	
el	 ejercicio	 para	 extraer	 los	 de	
posición	par	en	la	cola	
IV. Extraer pares
Diseñe	 una	 función	 que	 inserte	 en	
una	cola	de	enteros	los	elementos	de	
forma	ordenada	crecientemente	
V. Insertar en orden
Diseñe	 una	 función	 recursiva	 que	
devuelve	 la	 cola	 resultante	 de	
concatenar	dos	colas	
VI. Concatenar dos colas
Diseñe	 una	 función	 recursiva	 que	
devuelva	una	cola	con	los	elementos	
colocados	de	forma	inversa	a	otra	
VII. Cola inversa
Diseñe	una	función	que	devuelva	una	
cola	que	elimine	la	primera	aparición	
de	un	elemento		
VIII. Borrado de un elemento
Diseñe	una	función	que	devuelva	una	
cola	donde	se	hayan	eliminado	todas	
las	apariciones	de	un	elemento	
IX. Borrar todos
Diseñe	una	función	que	devuelva	una	
cola	con	los	elementos		que	preceden	
a	un	elemento	dado	
X. Cola prefijo
Diseñe	 una	 función	 que	 devuelva	 la	
cola	sufijo	que	sucede	a	un	elemento	
dado	
XI. Cola sufijo
Diseñe	 una	 función	 recursiva	 que	
devuelva	 una	 cola	 con	 todos	 los	
elementos	mayores	a	uno	dado	
XII. Cola mayores
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 15
Problemas	y	ejercicios	
Problemas	
Las	colas	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	problemas	de	
cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	 ejemplos	 de	
problemas	que	se	resuelven	con	el	uso	de	colas.	
Diferentes	 procesos	 de	 un	 sistema	 opera6vo	
compiten	en	ejecución	por	adquirir	el	uso	de	 	una	
impresora	 que	 esta	 a	 su	 vez	 conectada	 a	 varios	
equipos	 dispuestos	 en	 una	 red	 de	 área	 local.	 La	
cola	 de	 impresión	 es	 una	 abstracción	 donde	 se	
encolan	los	procesos	a	la	espera	de	ser	atendidos	
por	el	servidor	de	impresión	
Competición de procesos por un recurso
Competición de procesos por un recurso
En	 escenarios	 concurrentes	 los	 procesos	
productores	 deben	 comunicarse	 con	 los	
consumidores	 de	 información.	 Dado	 que	 el	 ritmo	
de	 trabajo	 de	 unos	 y	 otros	 no	 es	 el	 mismo	 se	
u6lizan	 colas	 de	 almacenamiento	 de	 mensajes	
como	mecanismo	de	amor6guación
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 16
Problemas	y	ejercicios	
Problemas	
Las	colas	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	problemas	de	
cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	 ejemplos	 de	
problemas	que	se	resuelven	con	el	uso	de	colas.	
En	 las	 redes	 de	 computadoras	 los	 disposi6vos	 de	
interconexión	 u6lizan	 colas	 para	 almacenar	 la	
información	 entrante	 y	 entregarla	 a	 sus	
des6natarios	 al	 ritmo	 que	 ellos	 requieran.	
Asimismo	 se	 u6liza	 esta	 técnica	 para	 realizan	
propagación	en	broadcast	o	mul6cast	
Enrutamiento de paquetes IP
Computación distribuida
En	computación	distribuida	se	u6lizan	sistemas	de	
mensajería	 encargados	 de	 mover	 la	 información.	
En	comunicación	punto	a	punto	las	colas	se	u6lizan	
para	persis6r	los	mensajes	y	garan6zar	la	entrega.	
En	 comunicación	 de	 eventos	 varios	 procesos	 se	
registran	 como	 escuchadores	 de	 una	 cola	 donde	
otros	 se	 publican	 eventos	 de	 un	 determinado	
tópico
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 17
Bibliograba	
BibliograTa	
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
Tipos	abstractos	de	datos	lineales.	Colas	
Javier Vélez Reyes jvelez@lsi.uned.es6 - 18
Bibliograba	
BibliograTa	
Bibliografía complementaria
Estructura de datos y algoritmos en java. A.
Drozdek. Thomsom. ISBN: 9706866116. 2007
Estructuras de datos con Java. J. Lewis, J.
Chase. Pearson – Addison Wesley. ISBN 13:
9788420541914
Javier	Vélez	Reyes	
jvelez@lsi.uned.es	
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	.	Grado	en	tecnologías	de	la	información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Parte	III	
Tipos	abstractos	de	
datos	jerárquicos
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
8	Tipos	abstractos	de	
datos	jerárquicos	
Árboles	generales
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 2
Índice	
Índice	
›  Introducción
›  Tipos abstractos de datos jerárquicos
›  El tipo abstracto de datos Árbol general
›  Interfaz del tipo abstracto de datos Árbol general
›  Implementaciones del tipo abstracto de datos Árbol general
›  Implementación dinámica
›  Implementación estática con array de posiciones variables
›  Algoritmos sobre Árboles generales
›  Recorrido de los elementos de un Árbol general
›  Búsqueda de un elemento sobre una Árboles general
›  Problemas y ejercicios
›  Bibliografía
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 3
Obje6vos	generales	
Obje8vos	
›  Conocer la interfaz del tipo abstracto de datos Árbol general
›  Aprender a implementar el TAD Árbol general mediante la interfaz TreeIF
›  En versión estática (con limitación explícita de capacidad máxima)
›  En versión dinámica (sin limitación explícita de capacidad máxima)
›  Conocer los principales problemas algorítmicos sobre árboles generales
›  Recorrido de los elementos de un árboles generales
›  Búsqueda de un elemento sobre un árboles generales
›  Practicar el diseño de funciones recursivas sobre árboles generales
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 4
Introducción	
Tipos	abstractos	de	datos	jerárquicos	
Los	6pos	abstractos	de	datos	jerárquicos	representan	abstracciones	en	las	que	los	datos	se	
distribuyen	a	través	de	relaciones	de	parento-filialidad	donde	cada	elemento	6ene	un	padre	
y	 varios	 hijos.	 En	 función	 del	 número	 máximo	 de	 hijos	 que	 puede	 tener	 un	 elemento	
dis6nguiremos	entre	árboles	binarios	(con	2	hijos	como	máximo)	y	árboles	generales	(sin	
limitación	 en	 el	 número	 de	 hijos).	 Aunque	 los	 segundos	 pueden	 considerarse	 una	
generalización	 de	 los	 primeros,	 ambos	 presentan	 implementaciones	 y	 escenarios	 de	 uso	
diferentes	lo	que	jus6fica	su	consideración	como	6pos	dis6ntos	
Tipos abstractos
de datos lineales
I. Árboles generales
II. Árboles binarios
Un árbol binario es un tipo especial de árbol donde cada elemento
del mismo puede referenciar a lo sumo a 2 hijos. Este tipo de
estructuras se utilizan frecuentemente para representar en
computación no sólo conjuntos de datos con una relación de
dependencia padre-hijo sino también para articular esquemas de
búsqueda eficientes
Los árboles generales pueden considerarse a todos los efectos una
generalización de los árboles binarios donde el número de hijos está
limitado por una constante k > 2 (o no existe limitación en el número
de hijos). Aunque, en principio, es posible expresar todo árbol
general como un árbol binario, existen situaciones en computación
donde este tipo de abstracciones tiene usos interesantes
Tema 7
}
Tema 8
}
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 5
Introducción	
El	8po	abstracto	de	datos	Árbol	general	
Un	árbol	general	es	una	estructura	que	organiza	una	colección	de	elementos	a	través	de	una	relación	
de	parento-filialidad	donde	cada	elemento	dispone	a	lo	sumo	de	un	padre	y	de	un	número	de	hijos	
no	prefijado	.	Si	un	elemento	no	6ene	padre	se	llama	nodo	raíz.	En	un	árbol	general	hay	siempre	un	y	
sólo	 un	 elemento	 raíz.	 Si	 un	 elemento	 no	 6ene	 hijos	 se	 llama	 elemento	 hoja.	 La	 definición	
computable	del	6po	se	establece	recursivamente	de	la	siguiente	manera	
Un	 árbol	 general	 es	 un	 6po	 abstracto	 de	 datos	 que	 da	 acceso	 directo	 a	 un	
elemento	llamado	raíz	y,	a	un	número	indeterminado	de	subárboles	que	dependen	
jerárquicamente	de	él	como	hijos	
Subárboles
Los árboles generales
pueden tener cualquier
número de hijos
0
1 7
2
4
8 9
3
5 6 Elemento hoja
Cuando un elemento
no tiene hijos se llama
hoja
Raíz
La raíz es el elemento del que
cuelga el resto de nodos
Niveles
El número de
niveles de un
árbol indica la
separación
máxima que hay
entre la raíz y la
hoja más
alejada de ésta
medida en
número de
arcos
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 6
Interfaz	del	6po	abstracto	de	datos	Árbol	general	
La	interfaz	del	8po	abstracto	de	datos	Árbol	general	TreeIF	<T>	
public	interface	TreeIF	<T>	
{				
	
				public	int	PREORDER		=	0;	
				public	int	POSTORDER	=	1;	
				public	int	LRBREADTH	=	2;	
				public	int	RLBREADTH	=	3;	
					
				/**	
					*	Devuelve	el	elemento	raiz	del	arbol.	
					*	@return	el	elemento	raiz	del	arbol.	
					*/	
				public	T	getRoot	();	
																
				/**	
					*	Establece	el	elemento	raiz.	
					*	@param	element	El	elemento	a	establecer.	
					*/	
				public	void	setRoot	(T	element);	
	
				/**	
					*	Devuelve	el	primer	los	hijos	de	un	arbol.	
					*	@return	los	hijos	de	un	arbol.	
					*/	
				public	ListIF	<TreeIF	<T>>	getChildren	();	
	
				/**	
					*	Devuelve	el	hijo	en	posición	pos.	
					*	@param	pos	La	posición	con	base	en	1.		
					*/	
				public	void	getChild	(int	pos);	
	
El	interfaz	de	Árbol	general	que	u6lizaremos	a	lo	largo	
de	 este	 curso,	 TreeIF	 está	 compuesto	 por	 las	
operaciones	que	describimos	a	con6nuación	
Recorridos	
Estas constantes sirven para identificar en el
método getIterator distintas estrategias de
recorrido de los elementos del árbol
Obtener	raíz	
Devuelve la raíz del árbol. Este método
devuelve un elemento de tipo T distinto de nulo
Establecer	raíz	
Esta operación establece el valor asignado a la
raíz de un del árbol. Si el valor es null la
operación no tiene efecto
Obtener	hijos		
Esta operación consultora devuelve la lista de
todos los subárboles que son hijos del nodo en
curso
1	
0	
Obtener	hijo	
Esta operación consultora devuelve el subárbol
que corresponde con el hijo ubicado en la
posición pos
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 7
Interfaz	del	6po	abstracto	de	datos	Árbol	general	
La	interfaz	del	8po	abstracto	de	datos	Árbol	general	TreeIF	<T>	
					
					
				/**	
					*	Devuelve	el	elemento	raiz	del	arbol.	
					*	@return	el	elemento	raiz	del	arbol.	
					*/	
				public	T	addChild	(TreeIF<T>	child);	
					
				/**	
					*	Extrae	un	subarbol	como	hijo.	
					*	@param	index	el	indice	del	subarbol	con	base	en	0.		
					*/	
				public	void	removeChild	(int	index);	
						
				/**	
					*	Devuelce	cierto	si	el	arbol	es	un	nodo	hoja.	
					*	@return	cierto	si	el	arbol	es	un	nodo	hoja.	
					*/	
				public	boolean	isLeaf	();		
									
				/**	
					*	Devuelve	un	iterador	para	la	lista.	
					*	@param	traversalType	El	tipo	de	recorrido.	
					*	@return	un	iterador	para	la	lista.	
					*/	
				public	IteratorIF<T>	getIterator	(int	traversalType);	
El	interfaz	de	Árbol	general	que	u6lizaremos	a	lo	largo	
de	 este	 curso,	 TreeIF	 está	 compuesto	 por	 las	
operaciones	que	describimos	a	con6nuación	
Añadir nuevo hijo
A través de esta operación se puede añadir un
nuevo subárbol como hijo más a la derecha en
la colección de hijos
Eliminar	hijo	
A través de esta operación se borra el hijo en
la posición indicada por index en la colección
Es	hoja	
Esta operación consultora indica si el nodo en
curso es un nodo hoja o no lo es
Recorrido	
Esta operación devuelve un iterador que
permite acceder a todos los elementos del
árbol
2	
false	
true	
1,2,3,4
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 8
Implementación	del	6po	abstracto	de	datos	Árbol	general	
Implementación	del	8po	abstracto	de	datos	Árbol	general	TreeIF	<T>	
Existen	 varias	 estrategias	 de	 implementación	 de	 árboles	 generales	 que	 responden	 al	
interfaz	TreeIF.	Éstas	se	dividen	en	implementaciones	dinámicas,	con	capacidad	indefinida	
para	 almacenar	 elementos	 e	 implementaciones	 está6cas,	 con	 una	 capacidad	 máxima	
limitada	establecida	por	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	dinámica	basada	en	cola	de	hijos	
Según	esta	estrategia	de	implementación,	un	árbol	es	un	objeto	que	representa	el	nodo	
raíz	del	mismo.	Cada	nodo	6ene	un	atributo	para	almacenar	el	valor	del	elemento	y	una	
cola	de	árboles	que	con6enen	referencias	a	los	hijos	
Elemento	
Almacena el valor
del dato en el nodo
1	
2	 5	
e	
Hijos	
Lista de referencias
a subárboles hijo
-
3	 - 3	 -
8	
7	 - 9	 -
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 9
Implementación	del	6po	abstracto	de	datos	Árbol	general	
Implementación	del	8po	abstracto	de	datos	Árbol	general	TreeIF	<T>	
Implementación	está8ca	mediante	array	de	posiciones	hijas	variables	
En	 esta	 implementación	 un	 árbol	 se	 representa	 como	 un	 array	 de	 nodos.	 El	 valor	 del	
nodo	raíz	se	encuentra	en	la	posición	0.	Cada	nodo	6ene	el	valor	del	elemento	que	porta	
y	 	la	lista	de	índices	que	indican	las	posiciones	dentro	del	array	donde	están	los	nodos	
hijos	
Capacidad	máxima	y	longitud		
La capacidad se expresa en
número de nodos	
8	 9	6	 7	4	 5	2	 3	0	 1	
Existen	varias	estrategias	de	implementación	árboles	generales	que	responden	al	interfaz	
TreeIF	anterior.	Éstas	se	dividen	en	implementaciones	dinámicas,	con	capacidad	indefinida	
para	 almacenar	 elementos	 e	 implementaciones	 está6cas,	 con	 una	 capacidad	 máxima	
limitada	establecida	por	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
0	
3
5
6
1	
9
4	
4
7
7	
2
1
8	 9	 2	5	 6	 3	
8
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 10
Algoritmos	sobre	árboles	generales	
Algoritmos	sobre	árboles	generales	
Como	viene	siendo	frecuente	a	lo	largo	de	este	curso,	los	tres	6pos	de	algoritmos	canónicos	
aplicables	a	cualquier	estructura	de	datos	 	son	recorrido,	búsqueda	y	ordenación.	En	este	
caso,	la	ordenación	debe	entenderse	como	una	reorganización	de	los	nodos	del	árbol	para	
favorecer	algún	criterio	(^picamente	la	búsqueda).	Sin	embargo,	no	estudiaremos	ningún	
algoritmo	de	ordenación	y	nos	centraremos	sólo	en	recorridos	y	búsquedas	
Algoritmos
sobre árboles
generales
I. Recorrido
El recorrido de los elementos de un árbol general devuelve un iterador que
permite acceder secuencialmente a los mismos según aparecen
almacenados en la estructura. Sin embargo, existen distintos criterios de
secuenciamiento que pueden aplicarse para construir un recorrido. Aquí
estudiaremos los más típicamente aplicados
II. Búsqueda
La búsqueda de un elemento sobre los nodos de un árbol general se realiza
de forma recursiva dada la definición del tipo lo que imprime un coste lineal al
algoritmo en el peor caso. La ventaja de este tipo de algoritmos, con respecto
a sus equivalentes en otras estructuras de datos es que el proceso no es
destructivo con lo que no se requiere utilizar un iterador (con copia) ni
reconstruir la estructura tras la aplicación del algoritmo
Independenciadela
implementación
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 11
Algoritmos	sobre	árboles	generales	
Recorrido	de	los	elementos	de	un	árbol	general	
Los	 recorridos	 que	 pueden	 aplicarse	 sobre	 las	 estructuras	 arborescentes	 son	 varios	 en	
función	de	la	estrategia	de	secuenciamiento	que	se	aplique	sobre	los	elementos	del	6po	
abstracto	 de	 datos.	 En	 concreto	 es	 posible	 dis6nguir	 4	 estrategias	 organizados	 de	 la	
siguiente	manera	
Recorridos
sobreárboles
I. Recorridos en profundidad
Se recorre el árbol recursivamente
en profundidad. En función de
donde se aloje, relativamente cada
nodo con respecto a sus hijos se
distinguen 2 recorridos
II. Recorridos en anchura
Preorden
Postorden
Cada nodo se inserta antes de
l a c o l e c c i ó n d e n o d o s
c o r r e s p o n d i e n t e a s u s
descendentes
Cada nodo se inserta detrás de
l a c o l e c c i ó n d e n o d o s
c o r r e s p o n d i e n t e a s u s
descendentes
S		A		C		O	
C		A		O		S	
Se recorre el árbol en anchura
colocando primero todos los
elementos del nivel k antes de
pasar a colocar los del nivel k + 1.
En función del orden en que se
disponen los elementos por niveles
se distinguen dos recorridos en
anchura
Anchura
Anchura inversa
Se disponen los elementos del
árbol por niveles de izquierda a
derecha y desde la raíz a las
hojas
Se disponen los elementos de
forma inversa a como establece
un recorrido en anchura
O		C		A		S	
S		A		C		O
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 12
Algoritmos	sobre	árboles	generales	
Recorrido	de	los	elementos	de	una	árbol	general	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 generales	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola	
public	class	TreeIterator<T>	implements	IteratorIF<T>		
{	
				private	IteratorIF<T>	iterator;	
					
				/**	
					*	Constructor	para	TreeIterator.	
					*	@param	handler	el	manejador	de	arboles.	
					*	@param	type	el	tipo	de	recorrido.	
					*/	
				public	TreeIterator	(TreeIF<T>	handler,	int	type)	
				{	
								QueueIF<T>	traverse	=	null;	
								switch	(type)	{	
												case	TreeIF.PREORDER:		traverse	=	preorder	(handler);		break;	
												case	TreeIF.POSTORDER:	traverse	=	postorder	(handler);	break;	
												case	TreeIF.LRBREADTH:	traverse	=	lrBreadth	(handler);	break;		
												case	TreeIF.RLBREADTH:	traverse	=	rlBreadth	(handler);	break;		
								}	
								this.iterator	=	new	QueueIterator<T>	(traverse);	
				}	
					
				/**	
					*	Devuelve	el	siguiente	elemento	de	la	iteracion.		
					*	@return	el	siguiente	elemento	de	la	iteracion.	
					*/	
				@Override	
				public	T	getNext	()		
				{	
								return	iterator.getNext	();	
				}	
La iteración de los elementos del árbol se delega
en el iterador de cola que es construido en el
constructor. La función de reset está garantizada
Iteración	con	reset	
La función de avance delega en el iterador de
cola que se ha construido previamente. Esta
aproximación simplifica las operaciones pero
penaliza el tiempo de la construcción del iterador
Avance	
Construcción	
En función del valor del parámetro del tipo de
recorrido, el constructor invoca a una u otra
función privada que devuelve una cola con los
elementos dispuestos en el orden apropiado.
Después se construye un iterador sobre la cola
resultante
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 13
Algoritmos	sobre	árboles	generales	
				/**	
					*	Devuelve	cierto	si	existen	mas	elementos	en	el	iterador.	
					*	@return	cierto	si	existen	mas	elementos	en	el	iterador.	
					*/	
				@Override	
				public	boolean	hasNext	()		
				{	
								return	iterator.hasNext	();	
				}	
					
				/**	
					*	Restablece	el	iterador	para	volver	a	recorrer	la	estructura.	
					*/	
				@Override		
				public	void	reset	()		{	
								iterator.reset	();	
				}	
					
				private	QueueIF<T>	preorder	(TreeIF<T>	tree)	
				{									
								QueueIF<T>	traverse	=	new	QueueDynamic<T>	();									
								T	element	=	tree.getRoot	();	
								traverse.add	(element);								
								IteratorIF	<TreeIF	<T>>	childrenIt	=	tree.getChildren	().getIterator	();	
								while	(childrenIt.hasNext	())	{	
												TreeIF		<T>	aChild	=	childrenIt.getNext	();	
												QueueIF	<T>	aTraverse	=	preorder	(aChild);	
												addAll	(traverse,	aTraverse);	
								}								
								return	traverse;	
				}	
La función de siguiente se delega sobre el
iterador de cola. Habrá siguientes elementos que
visitar si el iterador de cola aún no ha finalizado
Siguiente	
El recorrido en preorden inserta primero en la
cola cada nodo y luego construye recursivamente
las colas de los subárboles hijos. Mediante el
método addAll dichas colas se añaden, en ese
orden a la cola principal.
Preorden	
Reset	
La función de restablecimiento del iterador se
delega igualmente sobre el método homónimo del
iterador de colas
Recorrido	de	los	elementos	de	una	árbol	general	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 generales	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 14
Algoritmos	sobre	árboles	generales	
				private	QueueIF<T>	postorder	(TreeIF<T>	tree)	
				{	
								QueueIF<T>	traverse	=	new	QueueDynamic<T>	();									
								T	element	=	tree.getRoot	();	
								IteratorIF	<TreeIF	<T>>	childrenIt	=	tree.getChildren	().getIterator	();	
								while	(childrenIt.hasNext	())	{	
												TreeIF		<T>	aChild	=	childrenIt.getNext	();	
												QueueIF	<T>	aTraverse	=	postorder	(aChild);	
												addAll	(traverse,	aTraverse);	
								}								
								traverse.add	(element);								
								return	traverse;	
				}	
					
				private	QueueIF<T>	lrBreadth	(TreeIF<T>	tree)	{	
								QueueIF<T>	traverse	=	new	QueueDynamic	<T>	();		
								QueueIF<TreeIF<T>>	aux	=	new	QueueDynamic	<TreeIF<T>>	();	
									
								aux.add	(tree);	
								while	(!aux.isEmpty	())	{	
												TreeIF<T>	aTree	=	aux.getFirst	();	
												T	element	=	aTree.getRoot	();	
												IteratorIF	<TreeIF	<T>>	childrenIt	=	aTree.getChildren	().getIterator	();	
												while	(childrenIt.hasNext	())	{	
																TreeIF		<T>	aChild	=	childrenIt.getNext	();	
																aux.add	(aChild);	
												}													
												traverse.add	(element);	
												aux.remove	();	
								}								
								return	traverse;	
				}	
El recorrido en postorden inserta
primero los elementos de los subárboles
hijos y después anexa el nodo en curso.
Postorden	
El recorrido en anchura utiliza dos colas
para su construcción. En una se van
insertando los elementos resultantes del
recorrido. La otra es una cola auxiliar
que sirve para almacenar los subárboles
pendientes de ser procesados en cada
paso
Anchura	
Recorrido	de	los	elementos	de	una	árbol	general	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 generales	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 15
Algoritmos	sobre	árboles	generales	
				private	QueueIF<T>	rlBreadth	(TreeIF<T>	tree)	
				{	
								QueueIF<T>	traverse	=	lrBreadth	(tree);		
								StackIF<T>	aux	=	new	StackDynamic<T>	();	
								while	(!traverse.isEmpty	())	{	
												T	element	=	traverse.getFirst	();	
												aux.push	(element);	
												traverse.remove	();	
								}	
								while	(!aux.isEmpty	())	{	
												T	element	=	aux.getTop	();	
												traverse.add	(element);	
												aux.pop	();	
								}	
								return	traverse;	
				}	
								
				private	void	addAll	(QueueIF<T>	q,	QueueIF<T>	p)	
				{	
								while	(!p.isEmpty	())	{	
												T	element	=	p.getFirst	();	
												q.add	(element);	
												p.remove	();	
								}	
				}	
}	
					
La anchura inversa es el recorrido inverso al
anterior por tanto la implementación más sencilla
consiste en generar un recorrido en anchura e
invertirlo posteriormente. Para ello se utiliza una
pila. Primero se mueven los elementos de la cola
resultante a una pila. Después se extraen de la
cola para insertarlos en una pilla. Finalmente se
extraen de la pila para insertarlos nuevamente en
la cola
Anchura	inversa	
La función addAll inserta en una cola todos los
elementos de una segunda cola
Encolar	todos	
Recorrido	de	los	elementos	de	una	árbol	general	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 generales	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 16
Algoritmos	sobre	árboles	generales	
Búsqueda	de	un	elemento	sobre	un	árbol	general	
La	 búsqueda	 de	 un	 dato	 sobre	 los	 elementos	 contenidos	 en	 un	 árbol	 general	 es	 un	
problema	de	recorrido	que	termina	cuando	se	encuentra	el	elemento	buscado	dentro	de	la	
estructura	de	datos.	Dado	que	se	trata	de	un	6po	con	definición	recursiva	el	algoritmo	será	
esencialmente	iterar	sobre	cada	hijo	para	aplicar	sobre	él	recursivamente	el	algoritmo	
Búsqueda	recursiva	iterada	
				public	boolean	contains	(T	element)	
				{	
								if	(this.element.equals	(element))	return	true;	
								else	{	
												IteratorIF	<TreeIF	<T>>	childrenIt	=	children.getIterator	();	
												boolean	found	=	false;	
												while	(!found	&&	childrenIt.hasNext	())	{	
																TreeIF	<T>	aChild	=	childrenIt.getNext	();	
																found	=	aChild.contains	(element);	
												}	
												return	found;	
								}	
				}	
					
Como	puede	apreciarse	este	algoritmo	es	agnós6co	de	la	estructura	de	implementación	
subyacente	 ya	 que	 se	 apoya	 en	 operaciones	 definidas	 en	 el	 interfaz	 de	 árbol	 general	
TreeIF.	En	primer	lugar,	se	comprueba	si	el	nodo	raiz	coincide	con	el	elemento	buscado.	Si	
es	así,	hemos		terminado.	Si	no,	debemos	iterar	sobre	cada	uno	de	los	hijos	realizando	una	
búsqueda	con	cen6nela	en	la	colección	de	hijos	pero	recursiva	en	cada	hijo
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 17
Problemas	y	ejercicios	
Ejercicios	
Pueden	 encontrarse	 mul6tud	 de	 situaciones	 donde	 es	 necesario	 manipular	 la	 estructura	
interna	 de	 los	 elementos	 de	 un	 árbol	 general.	 A	 con6nuación	 presentamos	 algunos	
ejercicios	que	vienen	a	ejemplificar	tales	situaciones	
Diseñe	 una	 función	 devuelva	 el	
número	 de	 elementos	 que	 con6ene	
un	árbol	general	
I. Contar elementos
Diseñe	 una	 función	 que	 devuelve	 la	
suma	 de	 todos	 los	 elementos	 de	 un	
árbol	general	de	enteros	
II. Sumar elementos
Diseñe	 una	 función	 recursiva	 que	
devuelva	 una	 lista	 con	 todos	 los	
elementos	 pares	 de	 un	 árbol	 de	
enteros	
III. Encontrar pares
Diseñe	 una	 función	 recursiva	 que	
dado	 un	 árbol	 de	 enteros	 devuelva	
otro	 árbol	 solamente	 con	 los	
elementos	pares	
IV. Eliminar impares
Diseñe	una	función	dado	un	árbol	de	
enteros	 mul6plique	 el	 valor	 en	 cada	
nodo	por	su	altura	
V. Alturas
Diseñe	 una	 función	 recursiva	 que	
determine	 si	 dos	 árboles	 generales	
son	estructuralmente	idén6cos	
VI. Comparación de árboles
Diseñe	 una	 función	 recursiva	 que	
indique	si	dos	árboles	son	la	imagen	
especular	el	uno	del	otro	
VII. Imagen especular
Diseñe	 una	 función	 que	 dado	 un	
árbol		general	de	enteros	sus6tuya	el	
valor	 en	 cada	 nodo	 por	 el	 valor	
acumulado	 de	 todos	 los	 nodos	
anteriores	 a	 el	 en	 un	 recorrido	 en	
profundidad	
VIII. Sumar anteriores
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 18
Problemas	y	ejercicios	
Problemas	
Los	árboles	generales	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	
problemas	 de	 cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	
ejemplos	de	problemas	que	se	resuelven	con	el	uso	de	este	6po	abstracto	de	datos.	
Una	 cola	 de	 prioridad	 es	 un	 6po	 especial	 de	 cola	
donde	 las	 inserciones	 se	 realizan	 por	 orden	 de	
acuerdo	 a	 un	 criterio	 compara6vo	 entre	 los	
elementos	 de	 la	 cola.	 La	 implementación	 más	
eficiente	se	realiza	con	árboles	generales	donde	en	
el	nivel	k	están	los	elementos	de	prioridad	k	
Colas de prioridad
Árboles de decisión
En	 inteligencia	 ar6ficial	 y	 minería	 de	 datos	 se	
u6lizan	 árboles	 de	 decisión	 para	 representar	
problemas	 de	 decisión.	 Cada	 nodo	 representa	 un	
criterio	de	decisión	y	las	ramas	de	éste	las	posibles	
alterna6vas
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 19
Problemas	y	ejercicios	
Problemas	
Los	 datos	 almacenados	 en	 una	 base	 de	 datos	
suelen	 mantenerse	 ges6onados	 mediante	
estructuras	arbóreas	complejas		de	un	nivel	fijo	de	
profundidad	 (nivel	 raiz,	 nivel	 de	 página,	 nivel	 de	
hoja	y	nivel	de	registro,	etc.)	
Bases de datos
Juegos
La	 inteligencia	 ar6ficial	 de	 muchos	 juegos	 de	
estrategia,	 como	 el	 ajedrez	 o	 las	 tres	 en	 ralla,	
u6liza	 árboles	 para	 representar	 el	 espacio	 de	
búsqueda	de	las	alterna6vas	de	movimiento	dentro	
del	juego	valorando	con	una	función	de	u6lidad	el	
beneficio,	 posi6vo	 o	 nega6vo,	 de	 realizarlo.	 Una	
función	umbral	permite	tomar	la	decisión	
Las	árboles	generales	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	
problemas	 de	 cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	
ejemplos	de	problemas	que	se	resuelven	con	el	uso	de	este	6po	abstracto	de	datos.
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 20
Bibliograca	
BibliograTa	
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
Tipos	abstractos	de	datos	jerárquicos.	Árboles	generales	
Javier Vélez Reyes jvelez@lsi.uned.es7 - 21
Bibliograca	
BibliograTa	
Bibliografía complementaria
Estructura de datos y algoritmos en java. A.
Drozdek. Thomsom. ISBN: 9706866116. 2007
Estructuras de datos con Java. J. Lewis, J.
Chase. Pearson – Addison Wesley. ISBN 13:
9788420541914
Estrategias	de	programación	y	estructuras	de	datos	
Grado	en	Ingeniería	Informá8ca	
Grado	en	Tecnologías	de	la	Información	
Departamento	de	Lenguajes	y	Sistemas	informá6cos	
Javier	Vélez	Reyes	
				jvelez@lsi.uned.es 		
Departamento	de	Lenguajes	Y	Sistemas	InformáAcos	
UNED	
9	Tipos	abstractos	de	
datos	jerárquicos	
Árboles	binarios
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 2
Índice	
Índice	
›  Introducción
›  Tipos abstractos de datos jerárquicos
›  El tipo abstracto de datos Árbol binario
›  Interfaz del tipo abstracto de datos Árbol binario
›  Implementaciones del tipo abstracto de datos Árbol binario
›  Implementación dinámica
›  Implementación estática con array de posiciones fijas
›  Implementación estática con array de posiciones variables
›  Algoritmos sobre Árboles binarios
›  Recorrido de los elementos de un Árbol binario
›  Búsqueda de un elemento sobre una Árboles binarios
›  Ordenación y Equilibrado en Árboles binarios
›  Problemas y ejercicios
›  Bibliografía
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 3
Obje6vos	generales	
Obje8vos	
›  Conocer la interfaz del tipo abstracto de datos Árbol binario
›  Aprender a implementar el TAD Árbol binario mediante la interfaz BTreeIF
›  En versión estática (con limitación explícita de capacidad máxima)
›  En versión dinámica (sin limitación explícita de capacidad máxima)
›  Conocer los principales problemas algorítmicos sobre árboles binarios
›  Recorrido de los elementos de un árboles binarios
›  Búsqueda de un elemento sobre un árboles binarios
›  Ordenación y equilibrado de un árboles binarios
›  Practicar el diseño de funciones recursivas sobre árboles binarios
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 4
Introducción	
Tipos	abstractos	de	datos	jerárquicos	
Los	6pos	abstractos	de	datos	jerárquicos	representan	abstracciones	en	las	que	los	datos	se	
distribuyen	a	través	de	relaciones	de	parento-filialidad	donde	cada	elemento	6ene	un	padre	
y	 varios	 hijos.	 En	 función	 del	 número	 máximo	 de	 hijos	 que	 puede	 tener	 un	 elemento	
dis6nguiremos	entre	árboles	binarios	(con	2	hijos	como	máximo)	y	árboles	generales	(sin	
limitación	 en	 el	 número	 de	 hijos).	 Aunque	 los	 segundos	 pueden	 considerarse	 una	
generalización	 de	 los	 primeros,	 ambos	 presentan	 implementaciones	 y	 escenarios	 de	 uso	
diferentes	lo	que	jus6fica	su	consideración	como	6pos	dis6ntos	
Tipos abstractos
de datos lineales
I. Árboles generales
II. Árboles binarios
Un árbol binario es un tipo especial de árbol donde cada elemento
del mismo puede referenciar a lo sumo a 2 hijos. Este tipo de
estructuras se utilizan frecuentemente para representar en
computación no sólo conjuntos de datos con una relación de
dependencia padre-hijo sino también para articular esquemas de
búsqueda eficientes
Los árboles generales pueden considerarse a todos los efectos una
generalización de los árboles binarios donde el número de hijos está
limitado por una constante k > 2 (o no existe limitación en el número
de hijos). Aunque, en principio, es posible expresar todo árbol
general como un árbol binario, existen situaciones en computación
donde este tipo de abstracciones tiene usos interesantes
Tema 7
}
Tema 8
}
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 5
Introducción	
El	8po	abstracto	de	datos	Árbol	binario	
Un	árbol	binario	es	una	estructura	que	organiza	una	colección	de	elementos	a	través	de	una	relación	
de	parento-filialidad	donde	cada	elemento	dispone	a	lo	sumo	de	un	padre	y	a	lo	sumo	de	2	hijos.	Si	
un	 elemento	 no	 6ene	 padre	 se	 llama	 nodo	 raíz.	 En	 un	 árbol	 binario	 hay	 siempre	 un	 y	 sólo	 un	
elemento	raíz.	Si	un	elemento	no	6ene	hijos	se	llama	elemento	hoja.	La	definición	computable	del	
6po	se	establece	recursivamente	de	la	siguiente	manera	
Un	árbol	binario	es	un	6po	abstracto	de	datos	que	da	acceso	directo	a	un	elemento	
llamado	raíz	y,	a	lo	sumo,	a	dos	subárboles	que	dependen	jerárquicamente	de	él	
como	hijos	llamados	subárbol	izquierdo	y	subárbol	derecho	
Árbol binario
Los árboles binarios
pueden tener a lo sumo
dos elementos hijos
0
1 7
2 4 8 9
3 5 6
Elemento hoja
Cuando un elemento
no tiene hijos se llama
hoja
Raíz
La raíz es el elemento del que
cuelga el resto de nodos
Niveles
El número de
niveles de un
árbol indica la
separación
máxima que hay
entre la raíz y la
hoja más
alejada de ésta
medida en
número de
arcos
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 6
Interfaz	del	6po	abstracto	de	datos	Árbol	binario	
La	interfaz	del	8po	abstracto	de	datos	Árbol	binario	BTreeIF	<T>	
public	interface	BTreeIF	<T>	
{	
				
				public	int	PREORDER		=	0;	
				public	int	INORDER			=	1;	
				public	int	POSTORDER	=	2;	
				public	int	LRBREADTH	=	3;	
				public	int	RLBREADTH	=	4;	
					
				/**	
					*	Devuelve	el	elemento	raiz	del	arbol.	
					*	@return	el	elemento	raiz	del	arbol.	
					*/	
				public	T	getRoot	();	
					
				/**	
					*	Devuelve	el	subarbol	izquierdo	o	null	si	no	existe.	
					*	@return	el	subarbol	izquierdo.	
					*/	
				public	BTreeIF	<T>	getLeftChild	();	
					
				/**	
					*	Devuelve	el	subarbol	derecho	o	null	si	no	existe.	
					*	@return	el	subarbol	derecho.	
					*/	
				public	BTreeIF	<T>	getRightChild	();	
								
					
El	interfaz	de	Árbol	binario	que	u6lizaremos	a	lo	largo	
de	 este	 curso,	 BTreeIF	 está	 compuesto	 por	 las	
operaciones	que	describimos	a	con6nuación	
Recorridos	
Estas constantes sirven para identificar en el
método getIterator distintas estrategias de
recorrido de los elementos del árbol
Obtener	raíz	
Devuelve la raíz del árbol. Este método
devuelve un elemento de tipo T distinto de nulo
Obtener	hijo	izquierdo	
Esta operación consultora devuelve el subárbol
que cuelga como hijo izquierdo del árbol sobre
el que se consulta
Obtener	hijo	derecho	
Esta operación consultora devuelve el subárbol
que cuelga como hijo derecho del árbol sobre
el que se consulta
1
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 7
Interfaz	del	6po	abstracto	de	datos	Árbol	binario	
La	interfaz	del	8po	abstracto	de	datos	Árbol	binario	BTreeIF	<T>	
	
	
				/**	
					*	Establece	el	elemento	raiz.	
					*	@param	element	El	elemento	a	establecer.	
					*/	
				public	void	setRoot	(T	element);	
					
				/**	
					*	Establece	el	subarbol	izquierdo.	
					*	@param	tree	el	arbol	a	esablecer.		
					*/	
				public	void	setLeftChild	(BTreeIF	<T>	tree);	
					
			/**	
					*	Establece	el	subarbol	derecho.	
					*	@param	tree	el	arbol	a	esablecer.		
				*/	
				public	void	setRightChild	(BTreeIF	<T>	tree);			
					
				/**	
					*	Borra	el	subarbol	izquierdo.	
					*/	
				public	void	removeLeftChild	();	
					
				/**	
					*	Borra	el	subarbol	derecho.	
					*/	
				public	void	removeRightChild	();					
El	interfaz	de	Árbol	binario	que	u6lizaremos	a	lo	largo	
de	 este	 curso,	 BTreeIF	 está	 compuesto	 por	 las	
operaciones	que	describimos	a	con6nuación	
Asignar	elemento	raíz	
A través de esta operación se puede modificar
el valor del elemento raíz del árbol referido
Asignar	hijo	izquierdo		
A través de esta operación se cambia el
subárbol izquierdo por otro subárbol pasado
como parámetro
Asignar	hijo	izquierdo		
A través de esta operación se cambia el
subárbol izquierdo por otro subárbol pasado
como parámetro
Eliminar	hijo	izquierdo	
Esta operación elimina el subárbol izquierdo. Si
no existe hijo derecho se convierte en hoja
4	
Eliminar	hijo	derecho	
Esta operación elimina el subárbol derecho. Si
no existe hijo izquierdo se convierte en hoja
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 8
Interfaz	del	6po	abstracto	de	datos	Árbol	binario	
La	interfaz	del	8po	abstracto	de	datos	Árbol	binario	BTreeIF	<T>	
	
	
				/**	
					*	Devuelce	cierto	si	el	arbol	es	un	nodo	hoja.	
					*	@return	cierto	si	el	arbol	es	un	nodo	hoja.	
					*/	
				public	boolean	isLeaf	();		
					
				/**	
					*	Devuelve	cierto	si	el	arbol	es	vacio.	
					*	@return	cierto	si	el	arbol	es	vacio.	
					*/	
				public	boolean	isEmpty	();			
					
}	
El	interfaz	de	Árbol	binario	que	u6lizaremos	a	lo	largo	
de	 este	 curso,	 BTreeIF	 está	 compuesto	 por	 las	
operaciones	que	describimos	a	con6nuación	
Es	hoja	
Este predicado determina si el elemento de un
árbol es un elemento hoja o no
Recorrido	
Devuelve un iterador que permite recorrer los
elementos del árbol. Los tipos de recorridos
(ver principio) son preorden, inorden,
postorden, anchura y anchura inversa
falso	
cierto	
2,1,3	
inorden
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 9
Implementación	del	6po	abstracto	de	datos	Árbol	binario	
Implementación	del	8po	abstracto	de	datos	Árbol	binario	BTreeIF	<T>	
Existen	 varias	 estrategias	 de	 implementación	 árboles	 binarios	 que	 responden	 al	 interfaz	
BTreeIF	anterior.	Éstas	se	dividen	en	implementaciones	dinámicas,	con	capacidad	indefinida	
para	 almacenar	 elementos	 e	 implementaciones	 está6cas,	 con	 una	 capacidad	 máxima	
limitada	establecida	por	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	dinámica	basada	en	enlaces	izquierdo	y	derecho	
Según	esta	estrategia	de	implementación,	un	árbol	es	un	objeto	que	representa	el	nodo	
raíz	del	mismo.	Cada	nodo	6ene	un	atributo	para	almacenar	el	valor	del	elemento	y	dos	
atributos	de	6po	árbol	binario	para	referenciar	a	los	subárboles	izquierdo	y	derecho	
Elemento	
Almacena el valor
del dato en el nodo
1	
2	 -	5	
-	 -	3	 -	 -	4	 -	 -	6	
e	
Izquierdo	
Referencia al
hijo izquierdo
Derecho	
Referencia al
hijo derecho
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 10
Implementación	del	6po	abstracto	de	datos	Árbol	binario	
Implementación	del	8po	abstracto	de	datos	Árbol	binario	BTreeIF	<T>	
Existen	 varias	 estrategias	 de	 implementación	 árboles	 binarios	 que	 responden	 al	 interfaz	
BTreeIF	anterior.	Éstas	se	dividen	en	implementaciones	dinámicas,	con	capacidad	indefinida	
para	 almacenar	 elementos	 e	 implementaciones	 está6cas,	 con	 una	 capacidad	 máxima	
limitada	establecida	por	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	está8ca	mediante	array	de	posiciones	hijas	fijas	
En	esta	implementación	un	árbol	se	representa	como	un	array	de	elementos.	El	valor	del	
elemento	raíz	se	encuentra	en	la	posición	0.	Para	el	elemento	en	la	posición	i,	su	hijo	
izquierdo,	si	hay,	estará	en	la	posición	2*i+1	y	su	hijo	derecho	en	la	posición	2*i+2	
Niveles = 4
Capacidad	máxima	y	longitud		
La capacidad de esta implementación se expresa en
términos del número máximo de niveles. Si n	es el
número máximo de niveles hace falta un vector de
tamaño 2n+1.	 El	 árbol	 debe	 estar	 equilibrado	 y	 casi	
completo	para	un	aprovechamiento	eficiente	
-	 59 34 87 20 1 6 -	 -	 -	 -	
8	 9	6	 7	4	 5	2	 3	0	 1	 0	 1	 2	 3	 4	
1	0	
izquierdo	
derecho
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 11
Implementación	del	6po	abstracto	de	datos	Árbol	binario	
Implementación	del	8po	abstracto	de	datos	Árbol	binario	BTreeIF	<T>	
Existen	 varias	 estrategias	 de	 implementación	 árboles	 binarios	 que	 responden	 al	 interfaz	
BTreeIF	anterior.	Éstas	se	dividen	en	implementaciones	dinámicas,	con	capacidad	indefinida	
para	 almacenar	 elementos	 e	 implementaciones	 está6cas,	 con	 una	 capacidad	 máxima	
limitada	establecida	por	parámetro.	A	con6nuación	presentamos	varias	implementaciones	
Implementación	está8ca	mediante	array	de	posiciones	hijas	variables	
En	 esta	 implementación	 un	 árbol	 se	 representa	 como	 un	 array	 de	 nodos.	 El	 valor	 del	
nodo	raíz	se	encuentra	en	la	posición	0.	Cada	nodo	6ene	el	valor	del	elemento	que	porta	
y	dos	índices	que	indican	las	posiciones	dentro	del	array	donde	están	los	nodos	hijos	
Niveles = 4
Capacidad	máxima	y	longitud		
Ahora la capacidad se expresa en número de
nodos y el árbol no tiene porqué estas equilibrado	
8	 9	6	 7	4	 5	2	 3	0	 1	
Índice	izquierdo	
7
1
6
1
-	
-	
0
6
3 Índice	derecho	
elemento
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 12
Algoritmos	sobre	árboles	binarios	
Algoritmos	sobre	árboles	binarios	
Como	viene	siendo	frecuente	a	lo	largo	de	este	curso,	los	tres	6pos	de	algoritmos	canónicos	
aplicables	a	cualquier	estructura	de	datos	 	son	recorrido,	búsqueda	y	ordenación.	En	este	
caso,	la	ordenación	debe	entenderse	como	una	reorganización	de	los	nodos	del	árbol	para	
favorecer	algún	criterio	(`picamente	la	búsqueda).	Sin	embargo,	no	estudiaremos	ningún	
algoritmo	de	ordenación	y	nos	centraremos	sólo	en	recorridos	y	búsquedas	
Algoritmos
sobre árboles
binarios
I. Recorrido
El recorrido de los elementos de un árbol binario devuelve un iterador que
permite acceder secuencialmente a los mismos según aparecen
almacenados en la estructura. Sin embargo, existen distintos criterios de
secuenciamiento que pueden aplicarse para construir un recorrido. Aquí
estudiaremos los 5 más típicamente aplicados
II. Búsqueda
La búsqueda de un elemento sobre los nodos de un árbol binario se realiza
de forma recursiva dada la definición del tipo lo que imprime un coste lineal al
algoritmo en el peor caso. La ventaja de este tipo de algoritmos, con respecto
a sus equivalentes en otras estructuras de datos es que el proceso no es
destructivo con lo que no se requiere utilizar un iterador (con copia) ni
reconstruir la estructura tras la aplicación del algoritmo
Independenciadela
implementación
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 13
Algoritmos	sobre	árboles	binarios	
Recorrido	de	los	elementos	de	un	árbol	binario		
Los	 recorridos	 que	 pueden	 aplicarse	 sobre	 las	 estructuras	 arborescentes	 son	 varios	 en	
función	de	la	estrategia	de	secuenciamiento	que	se	aplique	sobre	los	elementos	del	6po	
abstracto	 de	 datos.	 En	 concreto	 es	 posible	 dis6nguir	 5	 estrategias	 organizados	 de	 la	
siguiente	manera	
Recorridos
sobreárboles
I. Recorridos en profundidad
Se recorre el árbol recursivamente
en profundidad. En función de
donde se aloje, relativamente cada
nodo con respecto a sus hijos
izquierdos y derechos se distinguen
3 recorridos en profundidad
II. Recorridos en anchura
Preorden
Inorden
Postorden
Cada nodo se inserta antes de
sus hijos izquierdos y derechos
Cada nodo se inserta entre sus
hijos izquierdos y derechos
Cada nodo se inserta detrás de
sus hijos izquierdos y derechos
S		A		C		O	
C		A		S		O	
c		A		O		S	
Se recorre el árbol en anchura
colocando primero todos los
elementos del nivel k antes de
pasar a colocar los del nivel k + 1.
En función del orden en que se
disponen los elementos por niveles
se distinguen dos recorridos en
anchura
Anchura
Anchura inversa
Se disponen los elementos del
árbol por niveles de izquierda a
derecha y desde la raíz a las
hojas
Se disponen los elementos de
forma inversa a como establece
un recorrido en anchura
O		C		A		S	
S		A		C		O
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 14
Algoritmos	sobre	árboles	binarios	
Recorrido	de	los	elementos	de	una	árbol	binario	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 binarios	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola	
class	BTreeIterator<T>	implements	IteratorIF<T>		
{					
					private	IteratorIF<T>	iterator;	
					
				/**	
					*	Constructor	para	QueueIterator.	
					*	@param	handler	el	manejador	de	arboles	binarios.	
					*	@param	type	el	tipo	de	recorrido.	
					*/	
				public	BTreeIterator	(BTreeIF<T>	handler,	int	type)	
				{	
								QueueIF<T>	traverse	=	null;	
								switch	(type)	{	
												case	BTreeIF.PREORDER:		traverse	=	preorder	(handler);		break;	
												case	BTreeIF.INORDER:			traverse	=	inorder	(handler);			break;	
												case	BTreeIF.POSTORDER:	traverse	=	postorder	(handler);	break;	
												case	BTreeIF.LRBREADTH:	traverse	=	lrBreadth	(handler);	break;		
												case	BTreeIF.RLBREADTH:	traverse	=	rlBreadth	(handler);	break;		
								}	
								this.iterator	=	new	QueueIterator<T>	(traverse);	
				}	
					
				/**	
					*	Devuelve	el	siguiente	elemento	de	la	iteracion.		
					*	@return	el	siguiente	elemento	de	la	iteracion.	
					*/	
				@Override	
				public	T	getNext	()		
				{	
								return	iterator.getNext	();	
				}	
La iteración de los elementos del árbol se delega
en el iterador de cola que es construido en el
constructor. La función de reset está garantizada
Iteración	con	reset	
La función de avance delega en el iterador de
cola que se ha construido previamente. Esta
aproximación simplifica las operaciones pero
penaliza el tiempo de la construcción del iterador
Avance	
Construcción	
En función del valor del parámetro del tipo de
recorrido, el constructor invoca a una u otra
función privada que devuelve una cola con los
elementos dispuestos en el orden apropiado.
Después se construye un iterador sobre la cola
resultante
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 15
Algoritmos	sobre	árboles	binarios	
Recorrido	de	los	elementos	de	una	árbol	binario	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 binarios	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola	
				/**	
					*	Devuelve	cierto	si	existen	mas	elementos	en	el	iterador.	
					*	@return	cierto	si	existen	mas	elementos	en	el	iterador.	
					*/	
				@Override	
				public	boolean	hasNext	()		
				{	
								return	iterator.hasNext	();	
				}	
					
				/**	
					*	Restablece	el	iterador	para	volver	a	recorrer	la	estructura.	
					*/	
				@Override		
				public	void	reset	()		
				{	
								iterator.reset	();	
				}	
					
				private	QueueIF<T>	preorder	(BTreeIF<T>	tree)	
				{	
								QueueIF<T>	traverse	=	new	QueueDynamic<T>	();	
								if	(tree	==	null)	return	traverse;									
								T	element	=	tree.getRoot	();	
								BTreeIF<T>	lTree	=	tree.getLeftChild	();	
								BTreeIF<T>	rTree	=	tree.getRightChild	();	
								QueueIF<T>	lTraverse	=	preorder	(lTree);	
								QueueIF<T>	rTraverse	=	preorder	(rTree);		
								traverse.add	(element);	
								addAll	(traverse,	lTraverse);	
								addAll	(traverse,	rTraverse);	
								return	traverse;			}	
La función de siguiente se delega sobre el
iterador de cola. Habrá siguientes elementos que
visitar si el iterador de cola aún no ha finalizado
Siguiente	
El recorrido en preorden inserta primero en la
cola cada nodo y luego construye recursivamente
las colas de los subárboles izquierdo y derecho.
Mediante el método allAll dichas colas se añaden,
en ese orden a la cola principal.
Preorden	
Reset	
La función de restablecimiento del iterador se
delega igualmente sobre el método homónimo del
iterador de colas
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 16
Algoritmos	sobre	árboles	binarios	
Recorrido	de	los	elementos	de	una	árbol	binario	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 binarios	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola	
				private	QueueIF<T>	inorder	(BTreeIF<T>	tree)	{	
								QueueIF<T>	traverse	=	new	QueueDynamic<T>	();	
								if	(tree	==	null)	return	traverse;									
								T	element	=	tree.getRoot	();	
								BTreeIF<T>	lTree	=	tree.getLeftChild	();	
								BTreeIF<T>	rTree	=	tree.getRightChild	();	
								QueueIF<T>	lTraverse	=	inorder	(lTree);	
								QueueIF<T>	rTraverse	=	inorder	(rTree);		
								addAll	(traverse,	lTraverse);	
								traverse.add	(element);	
								addAll	(traverse,	rTraverse);	
								return	traverse;		}	
			
				private	QueueIF<T>	postorder	(BTreeIF<T>	tree)	{	
								QueueIF<T>	traverse	=	new	QueueDynamic<T>	();	
								if	(tree	==	null)	return	traverse;									
								T	element	=	tree.getRoot	();	
								BTreeIF<T>	lTree	=	tree.getLeftChild	();	
								BTreeIF<T>	rTree	=	tree.getRightChild	();	
								QueueIF<T>	lTraverse	=	postorder	(lTree);	
								QueueIF<T>	rTraverse	=	postorder	(rTree);		
								addAll	(traverse,	lTraverse);	
								addAll	(traverse,	rTraverse);	
								traverse.add	(element);	
								return	traverse;			}		
					
				private	void	addAll	(QueueIF<T>	q,	QueueIF<T>	p)	{	
								while	(!p.isEmpty	())	{	
												T	element	=	p.getFirst	();	
												q.add	(element);	
												p.remove	();	}		
				}	
					
					
El recorrido en inorden inserta primero en la cola,
los elementos del subárbol izquierdo, luego el
nodo en curso y finalmente los elementos del
subárbol derecho.
Inorden	
El recorrido en postorden inserta primero los
elementos de los subárboles izquierdo y derecho
y después anexa el nodo en curso.
Postorden	
La función addAll inserta en una cola todos los
elementos de una segunda cola
Encolar	todos
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 17
Algoritmos	sobre	árboles	binarios	
Recorrido	de	los	elementos	de	una	árbol	binario	
Para	 implementar	 el	 iterador	 de	 los	 árboles	 binarios	 u6lizaremos	 una	 cola	 donde	 se	
almacenarán	en	la	construcción	los	elementos	dispuestos	adecuadamente	según	el	6po	de	
recorrido	seleccionado.	La	iteración	entonces	se	delegará	en	el	iterador	de	esa	cola	
				private	QueueIF<T>	lrBreadth	(BTreeIF<T>	tree)		{	
								QueueIF<T>	traverse	=	new	QueueDynamic<T>	();		
								QueueIF<BTreeIF<T>>	aux	=	new	QueueDynamic<BTreeIF<T>>	();								
								aux.add	(tree);	
								while	(!aux.isEmpty	())	{	
												BTreeIF<T>	aTree	=	aux.getFirst	();	
												T	element	=	tree.getRoot	();	
												BTreeIF<T>	lTree	=	aTree.getLeftChild	();	
												BTreeIF<T>	rTree	=	aTree.getRightChild	();	
												if	(lTree	!=	null)	aux.add	(lTree);	
												if	(rTree	!=	null)	aux.add	(rTree);	
												traverse.add	(element);	
												aux.remove	();	
								}								
								return	traverse;	
				}	
					
				private	QueueIF<T>	rlBreadth	(BTreeIF<T>	tree)	{	
								QueueIF<T>	traverse	=	lrBreadth	(tree);		
								StackIF<T>	aux	=	new	StackDynamic<T>	();	
								while	(!traverse.isEmpty	())	{	
												T	element	=	traverse.getFirst	();	
												aux.push	(element);	
												traverse.remove	();	
								}	
								while	(!aux.isEmpty	())	{	
												T	element	=	aux.getTop	();	
												traverse.add	(element);	
												aux.pop	();	
								}	
								return	traverse;	
				}	
El recorrido en anchura utiliza dos colas para su
construcción. En una se van insertando los
elementos resultantes del recorrido. La otra es
una cola auxiliar que sirve para almacenar los
subárboles pendientes de ser procesados en
cada paso
Anchura	
La anchura inversa es el recorrido inverso al
anterior por tanto la implementación más sencilla
consiste en generar un recorrido en anchura e
invertirlo posteriormente. Para ello se utiliza una
pila. Primero se mueven los elementos de la cola
resultante a una pila. Después se extraen de la
cola para insertarlos en una pilla. Finalmente se
extraen de la pila para insertarlos nuevamente en
la cola
Anchura	inversa
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 18
Algoritmos	sobre	árboles	binarios	
Búsqueda	de	un	elemento	sobre	un	árbol	binario	
La	búsqueda	de	un	dato	sobre	los	elementos	contenidos	en	un	árbol	binario	es	un	problema	
de	recorrido	que	termina	cuando	se	encuentra	el	elemento	buscado	dentro	de	la	estructura	
de	datos.	Dado	que	se	trata	de	un	6po	con	definición	recursiva	es	posible	aplicar	dos	6pos	
de	algoritmos.	La	búsqueda	aplica	una	estrategia	recursiva	para	recorrer	en	profundidad	el	
árbol.	 Alterna6vamente	 también	 se	 puede	 encontrar	 una	 solución	 itera6va	 basada	 en	
búsqueda	con	cen6nela	u6lizando	alguno	de	los	recorridos	secuenciales	que	acabamos	de	
describir.	
Búsqueda	binaria	
				@Override	
				public	boolean	contains	(T	element)	
				{	
									if	(element	==	null)	return	false;	
									return	element.equals	(getRoot	())		||	
									(getLeftChild	()	!=	null)	?		
													getLeftChild	().contains	(element)	:	false	||	
									(getRightChild	()	!=	null)	?		
													getRightChild	().contains	(element)	:	false;	
				}	
Es	 esta	 implementación	 se	 realiza	 una	
búsqueda	 con	 recursiva	 sobre	 la	 estructura	
de	nodos	del	árbol.	El	recorrido	corresponde	
a	un	preorden	
Búsqueda	con	cen8nela	
				@Override	
				public	boolean	contains	(T	element)	
				{	
								boolean	found	=	false;	
								Iterator<T>	it	=	getIterator	(this,	BTreeIF.INORDER);	
								while	(!found	&&	it.hasNext	())	{	
												T	anElement	=	it.getNext	();	
												found	=	anElement.equals	(element);	
								}	
								return	found;	
				}	
En	 la	 búsqueda	 con	 cen6nela	 la	 solución	
itera	 sobre	 los	 elementos	 de	 la	 estructura	
obtenidos	 a	 par6r	 de	 un	 iterador	 de	
cualquier	 6po	 de	 recorrido	 (por	 ejemplo	
inorden)
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 19
Algoritmos	sobre	árboles	binarios	
Árboles	binarios	de	búsqueda	
Los	 árboles	 binarios	 de	 búsqueda	 son	 u6lizados	 para	 disponer	 los	 elementos	 de	 un	
conjunto	de	tal	forma	que	se	op6mice	la	localización	de	los	mismos	alcanzándose	un	coste	
temporal	 logarítmico	 con	 respecto	 al	 volumen	 de	 datos	 medido	 para	 el	 peor	 caso.	 La	
disposición	de	los	elementos	debe	seguir,	naturalmente,	ciertos	criterios	de	orden	
Un	 árbol	 binario	 es	 de	 búsqueda	 si	 es	 vacio	 o	 la	 raíz	 es	 mayor	 que	 el	 máximo	
elemento	 del	 subárbol	 izquierdo	 y	 menor	 que	 el	 mínimo	 elemento	 del	 subárbol	
derecho	y,	a	su	vez,	ambos	subárboles	son	árboles	binarios	de	búsqueda	
8
3
1 6
4 7
10	
14	
13	
En	efecto,	este	es	un	árbol	binario	de	búsqueda	
puesto	que	verifica	que	todos	los	elementos	en	el	
subárbol	 izquierdo	 de	 cada	 nodo	 son	 menores	
que	 dicho	 nodo	 y	 los	 que	 se	 encuentran	 en	 el	
subárbol	derecho	mayores	que	el	mismo	
}
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 20
Algoritmos	sobre	árboles	binarios	
Árboles	binarios	de	búsqueda	
Un	árbol	de	búsqueda	es	equilibrado	si	
la	altura	de	los	subárboles	izquierdo	y	
derecho	es	exactamente	la	misma	
Árboles	equilibrados	
Para	garan6zar	realmente	un	coste	logarítmico	en	la	búsqueda	es	necesario	asegurarse	de	
que	 la	 estructura	 se	 man6ene	 equilibrada.	 Es	 decir,	 que	 la	 proporción	 de	 nodos	 a	 la	
izquierda	y	derecha	de	cualquier	nodo	sea	la	misma	
4
2 6
5 71 3
5
4
3
2
6
7
1
En	 una	 estructura	 jerárquica	
equilibrada	 el	 coste	 de	 la	
búsqueda	es	O	(log	n)		
}
Si	 el	 árbol	 binario	 de	
búsqueda	 no	 está	
equilibrado,	 en	 el	 caso	
peor	 se	 puede	 llegar	 a	
c o n v e r A r	 e n	 u n a	
estructura	 lineal	 con	
coste	O(n)	
}
Los	 árboles	 binarios	 de	 búsqueda	 son	 u6lizados	 para	 disponer	 los	 elementos	 de	 un	
conjunto	de	tal	forma	que	se	op6mice	la	localización	de	los	mismos	alcanzándose	un	coste	
temporal	 logarítmico	 con	 respecto	 al	 volumen	 de	 datos	 medido	 para	 el	 peor	 caso.	 La	
disposición	de	los	elementos	debe	seguir,	naturalmente,	ciertos	criterios	de	orden
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 21
Algoritmos	sobre	árboles	binarios	
Árboles	binarios	de	búsqueda	
Estrategias	de	equilibrado	y	rotaciones	
Los	 árboles	 binarios	 de	 búsqueda	 son	 u6lizados	 para	 disponer	 los	 elementos	 de	 un	
conjunto	de	tal	forma	que	se	op6mice	la	localización	de	los	mismos	alcanzándose	un	coste	
temporal	 logarítmico	 con	 respecto	 al	 volumen	 de	 datos	 medido	 para	 el	 peor	 caso.	 La	
disposición	de	los	elementos	debe	seguir,	naturalmente,	ciertos	criterios	de	orden	
Dado	 que	 la	 estructuración	 jerárquica	 de	 los	 árboles	 de	 búsqueda	 no	 responde	 a	 un	
requisito	del	problema	sino	a	una	disposición	conveniente	de	los	datos	es	posible	cambiar	
la	 misma	 según	 se	 hacen	 inserciones	 o	 extracciones	 para	 mantener	 el	 equilibrio.	 Las	
rotaciones		se	encargan	de	ello	(véase	hap://qma6ca.com)	
Rotación simple a derechas Rotación simple a izquierdas
8
4
62
10
n
n
n+1
4
8
106
2
n nn+1
n
n
n+1
n n n+1
4
3 8
96
8
4
63
9
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 22
Algoritmos	sobre	árboles	binarios	
Árboles	binarios	de	búsqueda	
Estrategias	de	equilibrado	y	rotaciones	
Los	 árboles	 binarios	 de	 búsqueda	 son	 u6lizados	 para	 disponer	 los	 elementos	 de	 un	
conjunto	de	tal	forma	que	se	op6mice	la	localización	de	los	mismos	alcanzándose	un	coste	
temporal	 logarítmico	 con	 respecto	 al	 volumen	 de	 datos	 medido	 para	 el	 peor	 caso.	 La	
disposición	de	los	elementos	debe	seguir,	naturalmente,	ciertos	criterios	de	orden	
Dado	 que	 la	 estructuración	 jerárquica	 de	 los	 árboles	 de	 búsqueda	 no	 responde	 a	 un	
requisito	del	problema	sino	a	una	disposición	conveniente	de	los	datos	es	posible	cambiar	
la	 misma	 según	 se	 hacen	 inserciones	 o	 extracciones	 para	 mantener	 el	 equilibrio.	 Las	
rotaciones		se	encargan	de	ello	(véase	hap://qma6ca.com)	
Rotación doble a derechas Rotación doble a izquierdas
n+1
n+1
n
n+1
9
105
1 7
86
7
5 9
1 6 8 10
n+1 n+1
n
n+1
3
5
9
7
6 8
10
n+1
n+1
n+1n
7
5
3
n+1
6
n
9
8 10
n+1 n+1
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 23
Algoritmos	sobre	árboles	binarios	
Árboles	binarios	de	búsqueda	
Tipos	de	árboles	de	búsqueda	
Los	 árboles	 binarios	 de	 búsqueda	 son	 u6lizados	 para	 disponer	 los	 elementos	 de	 un	
conjunto	de	tal	forma	que	se	op6mice	la	localización	de	los	mismos	alcanzándose	un	coste	
temporal	 logarítmico	 con	 respecto	 al	 volumen	 de	 datos	 medido	 para	 el	 peor	 caso.	 La	
disposición	de	los	elementos	debe	seguir,	naturalmente,	ciertos	criterios	de	orden	
Dado	que	la	restricción	acerca	del	equilibrio	es	demasiado	fuerte,	se	han	ideado	algunos	
6pos	de	árboles	de	búsqueda	cuasi-equilibrados	que	aplican	las	rotaciones	anteriores	como	
eje	fundamental	del	mantenimiento	logarítmico	de	las	operaciones	de	localización	
Árboles AVL Árboles roji – negros
En	 los	 árboles	 AVT	 las	 alturas	 de	 los	 hijos	 izquierdo	 y	
derecho	de	cada	subárbol	sólo	pueden	diferir,	a	lo	sumo	
en	 una	 unidad	 aplicándose	 rotaciones	 para	 el	
reequilibrado.	 Inserción	 y	 borrado	 son	 logarítmicas.	 La	
primera	debido	a	un	coste	constante	de	la	rotación.	La	
segunda	porque	la	propagación	solo	se	exAende	hasta	la	
raíz	 Para	 el	 resto	 de	 operaciones,	 el	 coste	 temporal,	
tanto	 promedio	 como	 en	 el	 caso	 peor,	 es	 también	
logarítmico	 aunque	 su	 coste	 espacial	 resulta	 lineal.	
[Weiss,	484-492]	[Drozdek,	255-260]
Los	árboles	roji-negros	son	estructuras	auto-equilibradas	en	
la	que	los	nodos	Aenen	un	atributo	adicional,	su	color	(rojo	o	
negro).	 La	 raíz	 es	 siempre	 negra.	 Los	 dos	 hijos	 de	 un	 nodo	
rojo	deben	ser	negros.	Todas	las	hojas	son	negras.	Y	todos	los	
caminos	 desde	 un	 nodo	 antecesor	 hasta	 cualquiera	 de	 sus	
hojas	deben	contener	el	mismo	número	de	nodos	negros.	Se	
uAlizan	 rotaciones	 para	 reequilibrar.	 Se	 pueden	 eliminar	 el	
segundo	recorrido	de	los	AVL	mediante	una	transformación	
descendente	 de	 algunos	 de	 los	 nodos	 (cambio	 de	 color,	
inserción	 de	 una	 hoja	 y	 rotación).	 Sin	 embargo,	 el	 borrado	
Aene	 una	 codificación	 compleja.	 Su	 coste	 temporal	 es	
logarítmico.	[Weiss,	492-505]
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 24
Algoritmos	sobre	árboles	binarios	
Árboles	binarios	de	búsqueda	
Tipos	de	árboles	de	búsqueda	
Los	 árboles	 binarios	 de	 búsqueda	 son	 u6lizados	 para	 disponer	 los	 elementos	 de	 un	
conjunto	de	tal	forma	que	se	op6mice	la	localización	de	los	mismos	alcanzándose	un	coste	
temporal	 logarítmico	 con	 respecto	 al	 volumen	 de	 datos	 medido	 para	 el	 peor	 caso.	 La	
disposición	de	los	elementos	debe	seguir,	naturalmente,	ciertos	criterios	de	orden	
Dado	que	la	restricción	acerca	del	equilibrio	es	demasiado	fuerte,	se	han	ideado	algunos	
6pos	de	árboles	de	búsqueda	cuasi-equilibrados	que	aplican	las	rotaciones	anteriores	como	
eje	fundamental	del	mantenimiento	logarítmico	de	las	operaciones	de	localización	
Árboles AA Árboles B
Los	árboles	AA	son	una	variante	de	los	roji-negros	cuyo	
atributo	adicional	es	el	nivel	en	lugar	del	color.	El	nivel	
representa	el	número	de	enlaces	a	hijos	izquierdos	en	el	
camino	hacia	la	hoja	(para		las	hojas	1).	Un	padre	rojo	y	
su	hijo	se	conectan	por	un	enlace	horizontal	y	Aenen	el	
mismo	nivel.	El	nivel	del	hijo	de	un	padre	negro	será	una	
unidad	menos	que	el		de	su	padre	.	La	inserción	siempre	
se	 realiza	 en	 el	 nivel	 más	 bajo	 del	 árbol.	 Se	 uAlizan	
rotaciones	 simples	 para	 reequilibrar	 si	 es	 preciso.	 El	
borrado	se	limita	a	la	eliminación	de	un	nodo	de	nivel	1.	
Su	coste	espacial	y	temporal	es	igual	al	de	los	rojinegros	
aunque	 los	 árboles	 AA	 se	 suelen	 aplanar	 algo	 más.		
[Weiss,	505-512]	
Los	árboles	B	son	una	generalización	de	los	árboles	binarios	
de	búsqueda	en	los	que	un	nodo	interno	puede	tener	más	de	
dos	 hijos	 hasta	 un	 cierto	 límite.	 OpAmizan	 la	 lectura	 de	
grandes	bloques	de	datos.	Un	árbol	B	de	orden	k	es	un	árbol	
k-ario	en	que	los	datos	se	almacenan	en	las	hojas.	Un	nodo	
interno	contendrá	k-1	claves	de	búsqueda,	donde	la	j-ésima	
clave	será	la	menor	del	árbol	j+1-ésimo.	La	raíz	bien	será	una	
hoja	 bien	 tendrá	 un	 rango	 de	 hijos	 entre	 2	 y	 k.	 Los	 nodos	
internos	Aenen	entre	k/2	y	k	hijos.	La	profundidad	de	todas	
las	hojas	es	la	misma	y	Aenen	entre	h/2	y	h	hijos,	donde	h	es	
un	 valor	 constante	 y	 prefijado.	 Al	 maximizar	 el	 número	 de	
hijos	 la	 altura	 decrece	 reduciéndose	 el	 coste	 de	 acceso	
(logaritmo	en	base	k)	y	los	reequilibrios.	[Weiss,	512-519]
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 25
Problemas	y	ejercicios	
Ejercicios	
Pueden	 encontrarse	 mul6tud	 de	 situaciones	 donde	 es	 necesario	 manipular	 la	 estructura	
interna	 de	 los	 elementos	 de	 un	 árbol	 binario.	 A	 con6nuación	 presentamos	 algunos	
ejercicios	que	vienen	a	ejemplificar	tales	situaciones	
Diseñe	 una	 función	 devuelva	 el	
número	 de	 elementos	 que	 con6ene	
un	árbol	binario	
I. Contar elementos
Diseñe	 una	 función	 que	 devuelve	 la	
suma	 de	 todos	 los	 elementos	 de	 un	
árbol	binario	de	enteros	
II. Sumar elementos
Diseñe	 una	 función	 recursiva	 que	
devuelva	 una	 lista	 con	 todos	 los	
elementos	 pares	 de	 un	 árbol	 de	
enteros	
III. Encontrar pares
Diseñe	 una	 función	 recursiva	 que	
dado	 un	 árbol	 binario	 de	 enteros	
devuelva	 otro	 árbol	 solamente	 con	
los	elementos	pares	
IV. Eliminar impares
Diseñe	 una	 función	 que	 reorganice	
los	 elementos	 de	 un	 árbol	 para	
conver6rlo	 en	 árbol	 binario	 de	
búsqueda	
V. Equilibrar
Diseñe	 una	 función	 recursiva	 que	
determine	si	dos	árboles	binarios	son	
estructuralmente	idén6cos	
VI. Comparación de árboles
Diseñe	 una	 función	 recursiva	 que	
indique	si	dos	árboles	binarios	son	la	
imagen	especular	el	uno	del	otro	
VII. Imagen especular
Diseñe	 una	 función	 que	 dado	 un	
árbol	 	binario	de	enteros	sus6tuya	el	
valor	 en	 cada	 nodo	 por	 el	 valor	
acumulado	 de	 todos	 los	 nodos	
anteriores	 a	 él	 en	 un	 recorrido	 en	
profundidad	
VIII. Sumar anteriores
Diseñe	una	función	que	determine	si	
un	 árbol	 binario	 es	 un	 árbol	 binario	
de	búsqueda	
IX. Es árbol de búsqueda
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 26
Problemas	y	ejercicios	
Problemas	
Las	árboles	binarios	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	
problemas	 de	 cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	
ejemplos	de	problemas	que	se	resuelven	con	el	uso	de	este	6po	abstracto	de	datos.	
La	 forma	 en	 que	 los	 compiladores	 manejan	 las	
expresiones	 aritmé6co-lógicas	 es	 mediante	 el	 uso	
de	 un	 árbol	 sintác6co	 donde	 los	 nodos	 hoja	
corresponden	 a	 operandos	 y	 los	 intermedios	 a	
operaciones.	 ¿Sabría	 idear	 un	 algoritmo	 que	
calcule	el	valor	de	la	siguiente	expresión	aritmé6ca	
expresada	en	forma	de	un	árbol	binario?	
Árboles sintácticos de operadores
Juegos y representación de escenarios 3D
En	 los	 motores	 de	 renderizado	 3D	 (ampliamente	
u6lizados	en	el	desarrollo	de	juegos	en	subje6vo)	la	
representación	 de	 los	 escenarios	 tridimensionales	
u6liza	 árboles	 binarios	 para	 descomponer	 las	
texturas	 poligonales	 en	 formas	 progresivamente	
más	sencillas.
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 27
Problemas	y	ejercicios	
Problemas	
Como	 aplicación	 especifica	 de	 los	 árboles	 de	
búsqueda	 binarios	 aparecen	 los	 diccionarios.	 Un	
diccionario	 es	 una	 estructura	 jerárquica	 sobre	 la	
cual	se	disponen	los	términos	en	las	hojas	mientras	
que	 los	 nos	 intermedios	 son	 prefijos	 organizados	
lexicográficamente	
Diccionarios
Codificación Huffman
La	 codificación	 Huffman	 es	 una	 técnica	 de	
compresión	de	datos	que	asigna	representaciones	
de	longitud	variable	a	cada	dato	en	función	se	su	
probabilidad	 de	 aparición	 (mayor	 probabilidad,	
menor	 longitud).	 La	 tabla	 de	 correspondencias	
suele	 representarse	 en	 forma	 de	 árbol	 binario	 (0	
izquierda,	 1	 derecha)	 para	 representar	 la	 cadena	
de	0s	y	1s	que	representa	cada	dato	
Las	árboles	binarios	son	un	6po	abstracto	de	datos	que	se	u6liza	recurrentemente	en	los	
problemas	 de	 cierta	 complejidad	 de	 programación.	 A	 con6nuación	 planteamos	 algunos	
ejemplos	de	problemas	que	se	resuelven	con	el	uso	de	este	6po	abstracto	de	datos.
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 28
Bibliograia	
BibliograSa	
Bibliografía básica
Estructuras de datos en java. Weiss, Mark
Allen. Pearson Addison – Wesley. ISBN
9788478290352
Tipos	abstractos	de	datos	jerárquicos.	Árboles	binarios	
Javier Vélez Reyes jvelez@lsi.uned.es8 - 29
Bibliograia	
BibliograSa	
Bibliografía complementaria
Estructura de datos y algoritmos en java. A.
Drozdek. Thomsom. ISBN: 9706866116. 2007
Estructuras de datos con Java. J. Lewis, J.
Chase. Pearson – Addison Wesley. ISBN 13:
9788420541914

Estrategias de Programación & Estructuras de Datos

  • 1.
  • 2.
  • 3.
  • 4.
    Presentación Javier Vélez Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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
  • 9.
  • 10.
    Introducción Javier Vélez Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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
  • 38.
  • 39.
    Estrategias de programación Javier Vélez Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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
  • 67.
  • 68.
    Análisis de la eficiencia de los algoritmos Javier Vélez Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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
  • 85.
    Análisis de la eficiencia de los algoritmos Javier Vélez Reyesjvelez@lsi.uned.es3 - 19 BibliograWa BibliograJa Bibliografía básica Estructuras de datos en java. Weiss, Mark Allen. Pearson Addison – Wesley. ISBN 9788478290352
  • 86.
    Análisis de la eficiencia de los algoritmos Javier Vélez Reyesjvelez@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
  • 87.
  • 88.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 Reyesjvelez@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 ()
  • 94.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 8 Introducción Partes de un contrato La especificación de un 6po abstracto de datos también incluye la definición del contrato para cada una de las operaciones del mismo. Estos contratos describen el efecto de las operaciones sobre el estado interno del 6po y prescriben las condiciones de deben sa6sfacer los parámetros de entrada pre: true stack.push (TElement e) post: stack.nElementos == stack’.nElementos + 1 AND stack.top () == e Especificación de 8pos abstractos de datos. Parte Semán8ca Las precondiciones de un contrato de operación describen las condiciones bajo las cuales puede invocarse de forma segura la misma para garan6zar un futuro estado consistente. Estas se expresan en términos de los posibles valores de cada parámetro de entrada o entrada / salida I. Precondiciones Las postcondiciones de un contrato de operación describen formalmente los efectos que provoca la invocación. Éstas se describen a par6r de los parámetros de entrada y salida de las operaciones y de las variables internas que referencian el estado anterior del 6po (U6lizaremos el apostrofe para referirnos a él) II. Postcondiciones
  • 95.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 9 Tipos abstractos de datos Catálogo de 8pos abstractos de datos Los 6pos abstractos de datos canónicos que aparecen recurrentemente dentro de la ingeniería del soWware se pueden clasificar según su creciente número de restricciones en relación a las polí6cas de organización y uso de sus datos internos. El siguiente diagrama ilustra lo expuesto Tipos abstractos de datos Estructuras sin orden Estructuras jerarquías Estructuras indexadas Estructuras lineales Bolsas Conjuntos Listas Pilas Cola Árboles Grafos Estructuras circulares Listas circulares Enumeración Matrices Matrices dispersas Estructuras tabulares Tablas de dispersión Diccionarios + -Restricciones
  • 96.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 10 Tipos abstractos de datos Catálogo de 8pos abstractos de datos Los 6pos abstractos de datos canónicos que aparecen recurrentemente dentro de la ingeniería del soWware se pueden clasificar según su creciente número de restricciones en relación a las polí6cas de organización y uso de sus datos internos. El siguiente diagrama ilustra lo expuesto Bolsas Estructuras Sin Orden Conjuntos - No existe orden entre los elementos - No existe orden entre los elementos - No se pueden repe6r elementos del mismo valor 1 2 1 2 53 4 1 2 6 7 53 4
  • 97.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 11 Tipos abstractos de datos Catálogo de 8pos abstractos de datos Los 6pos abstractos de datos canónicos que aparecen recurrentemente dentro de la ingeniería del soWware se pueden clasificar según su creciente número de restricciones en relación a las polí6cas de organización y uso de sus datos internos. El siguiente diagrama ilustra lo expuesto Listas Estructuras Linealmente ordenadas Pilas - Existe un orden total entre sus elementos - Existe un único punto de ataque - No existe destrucción 3 7 2 4 3 7 2 4 3 7 2 4 3 7 2 4 - Existe un orden total entre sus elementos - Existe un único punto de ataque llamado cima - Cima inmutable Primero / Siguiente Punto de interés Doble enlace Acceso por posición 3 7 2 Colas - Existe un orden total entre sus elementos - Un punto de ataque para inserción y otro para borrado - Cabeza inmutable 3 7 2 Pila Cola Inserción & borrado Borrado Inserción
  • 98.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 12 Tipos abstractos de datos Catálogo de 8pos abstractos de datos Los 6pos abstractos de datos canónicos que aparecen recurrentemente dentro de la ingeniería del soWware se pueden clasificar según su creciente número de restricciones en relación a las polí6cas de organización y uso de sus datos internos. El siguiente diagrama ilustra lo expuesto Grafos Estructuras Jerárquicas Árboles Binarios - Un conjunto de nodos sin orden - Un conjunto de aristas sin orden - Relación entre aristas & nodos - Variante de árbol general - Cada nodo 6ene a lo sumo un árbol izquierdo y derecho Árboles Binarios de Búsqueda - Variante de árbol binario - Los elementos se disponen en orden respecto a cada nodo - La máxima diferencia de niveles debe ser <= 2 Arboles Generales - Un nodo raíz como punto de acceso - Cada nodo puede tener varios hijos - Cada nodo sólo 6ene un padres - El nodo raíz no 6ene padre - Nodos hoja son nodos sin hijos 3 7 2 37 2 5 49 42 3 97 37 2 49 Árbol de Búsqueda Árbol Binario
  • 99.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 13 Tipos abstractos de datos Diseño de 8pos abstractos de datos Desde una perspec6va de diseño, podemos conceptualizar todos los 6pos abstractos que se aplican en el marco de la ingeniería del soWware como colecciones generales de información. A par6r de ahí cada 6po abstracto de datos puede entenderse como una especialización de este concepto. El modelo UML que u6lizaremos en este curso es el siguiente <<interface>> CollectionIF<T> <<interface>> SetIF<T> <<interface>> ListIF<T> <<interface>> StackIF<T> <<interface>> QueueIF<T> <<interface>> TreeIF<T> <<interface>> BTreeIF<T> <<interface>> IteratorIF<T> <<interface>> ComparatorIF<T> Sorter1 1. Es solo un ejemplo de clase con un método de ordenación
  • 100.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 14 Tipos abstractos de datos Diseño de 8pos abstractos de datos Como puede apreciarse en el diagrama UML de clases anterior, cada abstracción de datos se representa por una interfaz que especializa las capacidades generales de una colección abstracta. A lo largo de los siguientes capítulos describiremos en detalle los contenidos específicos de cada interfaz en relación a cada tema. Ahora presentamos las interfaces comunes de la asignatura, Collec6onIF, SetIF, IteratorIF y ComparatorIF public interface CollectionIF<E> { /** * Devuelve el número de elementos. * @return el número de elementos. */ public int size (); /** * Determina si la colección está vacía. * @return true si la colección está vacía */ public boolean isEmpty (); /** * Determina si un elemento está contenido. * @param el elemento a comprobar. * @return true, si está contenido. /* public boolean contains (E e); /** * Elimina todos los elementos. */ public void clear (); /** * Devuelve un iterador sobre la colección. * @return un iterador sobre la colección. */ public IteratorIF<E> iterator (); } 1 7 4 3 1 7 4 false true 1 7 4 false 1 7 4 true 3, 7, 1 7 4 1 7 4
  • 101.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 15 Tipos abstractos de datos Diseño de 8pos abstractos de datos Como puede apreciarse en el diagrama UML de clases anterior, cada abstracción de datos se representa por una interfaz que especializa las capacidades generales de una colección abstracta. A lo largo de los siguientes capítulos describiremos en detalle los contenidos específicos de cada interfaz en relación a cada tema. Ahora presentamos las interfaces comunes de la asignatura, Collec6onIF, SetIF, IteratorIF y ComparatorIF public interface SetIF<E> extends CollectionIF<E> { /** * Devuelve la unión de conjuntos. * @param el conjunto a unir. * @return el conjunto tras la union. */ public SetIF<E> union (SetIF<E> s); /** * Devuelve la intersección de conjuntos. * @param el conjunto a intersecar. * @return el conjunto tras la intersección. */ public SetIF<E> intersection (SetIF<E> s); ** * Devuelve la diferencia de conjuntos. * @param el conjunto a diferenciar. * @return el conjunto después de la diferencia. */ public SetIF<E> difference (SetIF<E> s); /** * Determina si un conjunto es subconjunto. * @param el conjunto a comprobar. * @return true si es subconjunto */ public boolean isSubset (SetIF<E> s); /** * Borra todos los elementos de una colección. * @param la colección. */ public void removeAll (CollectionIF<E> c); 1 7 4 2 4 1 7 42 1 7 4 2 4 4 1 7 4 2 4 2 1 7 4 2 4 false 4 7 4 2 4 2
  • 102.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 16 Tipos abstractos de datos Diseño de 8pos abstractos de datos Como puede apreciarse en el diagrama UML de clases anterior, cada abstracción de datos se representa por una interfaz que especializa las capacidades generales de una colección abstracta. A lo largo de los siguientes capítulos describiremos en detalle los contenidos específicos de cada interfaz en relación a cada tema. Ahora presentamos las interfaces comunes de la asignatura, Collec6onIF, SetIF, IteratorIF y ComparatorIF public interface IteratorIF<T> { /** * Devuelve el siguiente elemento de la iteracion. * @return el siguiente elemento de la iteracion. */ public T getNext (); /** * Indica si hay más elemento en la iteración. * @return true si hay más elemento en la iteración */ public boolean hasNext (); /** * Restablece el iterador para volver al inicio. */ public void reset (); } 1 7 42 1 1 7 42 true 1 7 42 false 1 7 42
  • 103.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 17 Tipos abstractos de datos Diseño de 8pos abstractos de datos Como puede apreciarse en el diagrama UML de clases anterior, cada abstracción de datos se representa por una interfaz que especializa las capacidades generales de una colección abstracta. A lo largo de los siguientes capítulos describiremos en detalle los contenidos específicos de cada interfaz en relación a cada tema. Ahora presentamos las interfaces comunes de la asignatura, Collec6onIF, SetIF, IteratorIF y ComparatorIF public interface ComparatorIF<T> { public static int LT = -1; public static int EQ = 0; public static int GT = 1; /** * Compara dos elementos para indicar si el primero es * menor, igual o mayor que el segundo elemento. * @param e1 el primer elemento. * @param e2 el segundo elemento. * @return el orden de los elementos. */ public int compare (T e1, T e2); /** * Indica si un elemento es menor que otro. * @param e1 el primer elemento. * @param e2 el segundo elemento. * @return true si un elemento es menor que otro. */ public boolean lt (T e1, T e2); /** * Indica si un elemento es igual que otro. * @param e1 el primer elemento. * @param e2 el segundo elemento. * @return true si un elemento es igual que otro. */ public boolean eq (T e1, T e2); /** * Indica si un elemento es mayor que otro. * @param e1 el primer elemento. * @param e2 el segundo elemento. * @return true si un elemento es mayor que otro. */ public boolean gt (T e1, T e2); }
  • 104.
    Tipos Abstractos de Datos Javier Vélez Reyesjvelez@lsi.uned.es4 - 18 Bibliograga BibliograVa 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
  • 105.
  • 106.
  • 107.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 2 Índice Índice ›  Introducción ›  Tipos abstractos de datos lineales ›  El tipo abstracto de datos lista ›  Interfaz del tipo abstracto de datos lista ›  Implementaciones del tipo abstracto de datos lista ›  Implementación dinámica ›  Implementación estática ›  Algoritmos sobre listas ›  Recorrido de los elementos de una lista ›  Búsqueda de un elemento sobre una lista ›  Ordenación de los elementos de una lista ›  Ejercicios ›  Bibliografía
  • 108.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 3 Obje6vos generales Obje8vos ›  Comprender que son los tipos abstractos de datos lineales ›  Conocer la interfaz del tipo abstracto de datos Lista ›  Aprender a implementar el TAD Lista mediante la interfaz ListIF ›  En versión estática (con limitación explícita de capacidad máxima) ›  En versión dinámica (sin limitación explícita de capacidad máxima) ›  Conocer los principales problemas algorítmicos sobre listas ›  Recorrido de los elementos de una lista ›  Búsqueda de un elemento sobre una lista ›  Ordenación de los elementos de una lista ›  Practicar el diseño de funciones recursivas sobre listas
  • 109.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 4 Introducción Tipos abstractos de datos lineales Los 6pos abstractos de datos lineales representan abstracciones en las que los datos son organizados de forma secuencial. A con6nuación se muestran los diferentes TADs que caen dentro de esta categoría y que se diferencian, esencialmente, en la forma en que ofrecen acceso a sus datos Tipos abstractos de datos lineales I. Listas II. Pilas III. Colas El tipo abstracto de datos Lista representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el principio, que puede moverse recursivamente haciendo referencia a otras sublistas El tipo abstracto de dato Pila representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el principio según la política de acceso último en entrar, primero en salir El tipo abstracto de dato Cola representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el final y por el principio respectivamente de acuerdo a la política de primero en entrar, primero en salir Tema 4 } Tema 5 } Tema 6 }
  • 110.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 5 Introducción El 8po abstracto de datos lista Las listas son abstracciones de datos que organizan una colección de elementos de manera secuencial, donde a cada elemento le sigue un único elemento siguiente. La definición del 6po establece un modelo posicional donde cada elemento se iden6fica por un índice que permite su acceso directo Una lista es un 6po abstractos de datos que organiza una colección de elementos de forma secuencial. Su definición permite acceder a sus elementos de forma directa a través de un índice posicional 2 3 4 5 6 7 8 9 elementos Cada posición de la lista guarda un valor de tipo genérico 1 posición Cada elemento dentro de la lista adquiere un índice único que identifica su posición y permite accederlo de forma directa
  • 111.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 6 Interfaz del 6po abstracto de datos Lista La interfaz del 8po abstracto de datos Lista ListIF <T> public interface ListIF<T> extends CollectionIF<T> { /** * Devuelve el elemento en la posición indicada. * @param pos La posición del elemento. * @return el elemento en la posición indicada. */ public T get (int pos); /** * Sobrescribe el elemento en la posición indicada. * @param element El elemento sustituto. * @param pos La posición que ocupará el elemento. */ public ListIF<T> set (int pos, T element); /** * Inserta un nuevo elemento a la lista. * @param element El elemento a añadir. * @param pos La posición donde debe añadirse. */ public void insert (T element, int pos); /** * Borra el elemento en la posición indicada. * @param la posición del elemento a borrar. */ public void remove (int pos); } El interfaz de listas que u6lizaremos a lo largo de este curso, ListIF esta compuesto por las operaciones que describimos a con6nuación 1 7 44 2 1 7 4 32, 1 7 3 1 7 4 2 1 7 1 7 4 32, 7 3 41
  • 112.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 7 Implementación del 6po abstracto de datos Lista Implementación del 8po abstracto de datos Lista ListIF <T> Existen varias estrategias para implementar listas que respondan al interfaz ListIF anterior. En general, éstas se dividen en implementaciones dinámicas, que ar6culan listas de capacidad indefinida e implementaciones está6cas, con una capacidad máxima limitada y establecida como parámetro. Aquí presentamos una conveniente. Implementación dinámica basada cadena de nodos Según esta estrategia de implementación, una lista está formada por un atributo que representa el elemento en la cabeza y otro que es una referencia a una lista que representa el resto de la lista. De esta manera una lista es una colección encadenada de pares (primero, siguiente). 1 2 3 4 Primero y resto Internamente cada objeto Lista contiene un atributo para representar el elemento en cabeza de lista y un atributo del tipo definido ListIF que representa una referencia al resto de elementos tras la cabeza Lista La lista es una secuencia de pares (primero, resto) a c a b a d a e n u n p a r fantasma
  • 113.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 8 Algoritmos sobre listas Algoritmos sobre listas Estudiaremos 3 6pos de problemas recurrentes sobre la interfaz de listas ListIF: recorrido de los elementos de una lista, búsqueda de un elemento entre los elementos de una lista y ordenación ascendente de los elementos de una lista. La definición recursiva del 6po condiciona las estrategias algorítmicas que pueden u6lizarse. Algoritmos sobre listas I. Recorrido El recorrido de los elementos de una lista devuelve un iterador que permite procesarlos secuencialmente según aparecen almacenados en la estructura. Como la definición es recursiva solo el recorrido directo será estudiado. El recorrido inverso es fácilmente implementable y se deja como ejercicio II. Búsqueda La búsqueda de un elemento sobre los elementos de una lista se realiza de forma secuencial dada la definición recursiva del tipo lo que imprime un coste lineal al algoritmo. Se estudiará el predicado de contención dejando como ejercicio la búsqueda del mínimo y el máximo III. Ordenación La ordenación de los elementos de una lista, reorganiza sus elementos de forma que se dispongan ascendentemente de acuerdo a cierto criterio de comparación que se recibe como parámetro. En este capítulo estudiaremos dos conocidos métodos de ordenación en listas: ordenación por inserción (insert sort) y ordenación por mezcla (merge sort).La ordenación descendente es similar y se deja como ejercicio. Independenciadela implementación
  • 114.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 9 Algoritmos sobre listas Recorrido de los elementos de una lista Para ar6cular el recorrido secuencial de los elementos de una lista debe implementarse el interfaz IteratorIF. Las implementaciones de ListIF anteriores construyen una copia de la lista como manejador para garan6zar que la iteración no modifique el estado del 6po class ListIterator<T> implements IteratorIF<T> { private ListIF<T> handler = null; private int pos; /** * Constructor para ListIterator. * @param handler el manejador de listas. */ public ListIterator (ListIF<T> handler) { this.handler = handler; this.pos = 0; } /** * Devuelve el siguiente elemento de la iteracion. * @return el siguiente elemento de la iteracion. */ @Override public T getNext () { return this.handler.get (this.pos++); } Se mantienen un manejadores de la lista y un índice posicional que indica a la posición del elemento en curso dentro de la iteración Iteración con reset La operación de avance devuelve el elemento apuntado por el índice posicional y lo actualiza para marcar el recorrido recorrido. Para invocar esta operación con seguridad hay que asegurarse de que el manejador no apunta a la lista vacía Avance 3 4 1 2 getNext()
  • 115.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 10 Algoritmos sobre listas Recorrido de los elementos de una lista Para ar6cular el recorrido secuencial de los elementos de una lista debe implementarse el interfaz IteratorIF. Las implementaciones de ListIF anteriores construyen una copia de la lista como manejador para garan6zar que la iteración no modifique el estado del 6po /** * Devuelve cierto si existen mas elementos a iterar. * @return cierto si existen mas elementos a iterar. */ @Override public boolean hasNext () { return this.pos < this.handler.size (); } /** * Restablece el iterador para volver al inicio. */ @Override public void reset () { this.pos = 0; } @Override public int hashCode () { ... } @Override public boolean equals (Object o) { ... } @Override public String toString () {...} } Para saber si el iterador contiene más elementos y por tanto puede volver a invocarse la operación de avance o no, hay que preguntar si el índice posicional ha alcanzado el final de la lista Hay siguiente Una vez que un iterador ha llegado a su fin sólo se puede construir otro iterador, basta con volver a la posición inicial el índice posicional Reset 3 4 1 2 reset ()
  • 116.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 11 Algoritmos sobre listas Búsqueda de un elemento sobre una lista La búsqueda de un dato sobre los elementos contenidos en una lista es un problema de recorrido secuencial que termina cuando se encuentra una cabeza que corresponde con el dato buscado. En este sen6do puede aplicarse un algoritmo recursivo o aprovechar el iterador anterior para resolverlo itera6vamente mediante búsqueda con cen6nela Búsqueda itera8va con cen8nela /** * Devuelve cierto si la lista contiene el elemento. * @param element El elemento buscado. * @return cierto si la lista contiene el elemento. */ @Override public boolean contains (T element) { IteratorIF<T> listIt = this.iterator (); boolean found = false; while (!found && listIt.hasNext ()) { T anElement = listIt.getNext (); found = anElement.equals (element); } return found; } En la búsqueda con cen6nela se itera sobre la lista y se u6liza una guarda (cen6nela) para indicar el momento en que se ha encontrado el elemento y la búsqueda puede parar Búsqueda recursiva /** * Devuelve cierto si la lista contiene el elemento. * @param element El elemento buscado. * @return cierto si la lista contiene el elemento. */ @Override public boolean contains (T element) { this.contains (element, 0); } private boolean contains (T e, int pos) return pos >= this.size () ? false : this.get (pos).equals (e) || contains (e, pos+1) } En la búsqueda recursiva se comprueba si la cabeza se corresponde con el elemento buscado. Si es así el algoritmo termina devolviendo cierto y si no, se recurre sobre el resto de la lista para buscar el elemento
  • 117.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 12 Algoritmos sobre listas Ordenación de los elementos de una lista Los algoritmos de ordenación que pueden aplicarse sobre listas, son rela6vamente pocos, en comparación con los que pueden aplicarse sobre estructuras de indexación. En concreto nosotros discu6remos en este capítulo la ordenación por inserción y la ordenación por mezcla Si la lista es vacía se devuelve ésta. Sino, se ordena el resto de la lista recursivamente y se inserta en ella el primer elemento en la posición adecuada según el criterio de orden 3 2 5 7 3 7 5 2 Ordenación por inserción Ordenación por burbuja Se recorre en doble vuelta los elementos del vector con 2 pivotes anidados i y j. El pivote i avanza en 1..N y j en i+1..N. En cada iteración se comparan los valores en i y j y si es necesario se permutan 3 2 5 7 3 7 5 2 Ordenación por mezcla Durante la primera fase, el algoritmo divide recursivamente el problema en subproblemas de la mitad de tamaño. Este proceso requiere recorrer la lista y tiene un coste de complejidad lineal Una vez alcanzado elementos atómicos, la fase de mezcla combina las soluciones ordenando cada subproblema por combinación de sus elementos. De esta forma, se obtiene, al final, el array completamente ordenado
  • 118.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 13 Ejercicios Ejercicios Dado el carácter recursivo de la definición del 6po abstracto de datos ListIF, la mayoría de algoritmos sobre listan 6enen un planteamiento recursivo. A con6nuación se presentan una colección de problemas [picos sobre listas para que se resuelvan de esta manera Diseñe una función recursiva que calcule el número de elementos que con6ene una lista I. Longitud de una lista Diseñe una función recursiva que compare lexicográficamente 2 listas de caracteres. II. Comparar dos listas Diseñe una función que dada una lista determine si una lista es sublista de otra dada de mayor tamaño III. Sublista Diseñe una función recursiva implemente la ordenación por inserción IV. Ordenar por inserción Diseñe una función recursiva implemente la ordenación por mezcla V. Ordenar por mezcla Diseñe una función recursiva que devuelve la lista resultante de concatenar dos listas VI. Concatenar dos listas Diseñe una función recursiva que devuelva una lista con los elementos colocados de forma inversa a otra VII. Lista inversa Diseñe una función recursiva implemente el método de ordenación de la burbuja VIII. Ordenar por burbuja Diseñe una función que devuelva una lista donde se hayan eliminado todas las apariciones de un elemento IX. Borrar todos Diseñe una función recursiva que devuelva una sublista prefijo que precede a un elemento dado X. Lista prefijo Diseñe una función recursiva que devuelva la lista sufijo que sucede a un elemento dado XI. Lista sufijo Diseñe una función recursiva que devuelva una lista con todos los elementos mayores a uno dado XII. Lista mayores
  • 119.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 14 Ejercicios Ejercicios Dado el carácter recursivo de la definición del 6po abstracto de datos ListIF, la mayoría de algoritmos sobre listan 6enen un planteamiento recursivo. A con6nuación se presentan una colección de problemas [picos sobre listas para que se resuelvan de esta manera Diseñe una función recursiva que sume 1 a todo los elementos de una lista de enteros XIII. Sumar 1 Diseñe una función que indique si dos elementos pertenecen a una lista dada XIV. Pertenecen 2 Diseñe una función que dadas dos listas que representan 2 conjuntos devuelva la lista del conjunto unión XV. Unión de conjuntos Diseñe una función que dadas dos listas devuelva los elementos comunes a ambas XVI. Intersección de listas Diseñe una función que recibiendo un conjunto en forma de lista genere una lista de listas con las partes del conjunto XVII. Partes de un conjunto Diseñe una función recursiva que dada una lista de ceros y unos devuelva el complemento a 1 XVIII. Complemento a 1 Diseñe una función que cuente el numero de veces que determinado elemento aparece en una lista XIX. Contador Diseñe una función que genere una lista con el número de veces que aparece cada elemento de una lista XX. Lista contador Diseñe una función recursiva que calcule el producto escalar de dos vectores expresados en listas XXI. Producto escalar Dadas dos listas que representan números naturales, implemente el algoritmo de suma generando una lista resultado XXII. Suma de listas Diseñe una función que dada una lista de dígitos construya el número natural que representa XXIII. Convertir a número Diseñe una función que dado un número genere una lista de dígitos que lo represente XXIV. Convertir a lista
  • 120.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 15 Bibliogra^a BibliograMa Bibliografía básica Estructuras de datos en java. Weiss, Mark Allen. Pearson Addison – Wesley. ISBN 9788478290352
  • 121.
    Tipos abstractos de datos lineales. Listas Javier Vélez Reyesjvelez@lsi.uned.es4 - 16 Bibliogra^a BibliograMa Bibliografía complementaria Estructura de datos y algoritmos en java. A. Drozdek. Thomsom. ISBN: 9706866116. 2007 Estructuras de datos con Java. J. Lewis, J. Chase. Pearson – Addison Wesley. ISBN 13: 9788420541914
  • 122.
  • 123.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 2 Índice Índice ›  Introducción ›  Tipos abstractos de datos lineales ›  El tipo abstracto de datos Pila ›  Interfaz del tipo abstracto de datos Pila ›  Implementaciones del tipo abstracto de datos Pila ›  Implementación dinámica ›  Implementación estática ›  Implementación con Lista ›  Algoritmos sobre Pilas ›  Recorrido de los elementos de una Pila ›  Búsqueda de un elemento sobre una Pila ›  Problemas y ejercicios ›  Bibliografía
  • 124.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 3 Obje6vos generales Obje8vos ›  Conocer la interfaz del tipo abstracto de datos Pila ›  Aprender a implementar el TAD Pila mediante la interfaz StackIF ›  En versión estática (con limitación explícita de capacidad máxima) ›  En versión dinámica (sin limitación explícita de capacidad máxima) ›  Utilizando una lista ›  Conocer los principales problemas algorítmicos sobre pilas ›  Recorrido de los elementos de una pila ›  Búsqueda de un elemento sobre una pila ›  Practicar el diseño de funciones recursivas sobre pilas
  • 125.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 4 Introducción Tipos abstractos de datos lineales Los 6pos abstractos de datos lineales representan abstracciones en las que los datos son organizados de forma secuencial. A con6nuación se muestran los diferentes TADs que caen dentro de esta categoría y que se diferencian, esencialmente, en la forma en que se ofrecen acceso a sus datos Tipos abstractos de datos lineales I. Listas II. Pilas III. Colas El tipo abstracto de datos Lista representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el principio, que puede moverse recursivamente haciendo referencia a otras sublistas El tipo abstracto de dato Pila representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el principio según la política de acceso último en entrar, primero en salir El tipo abstracto de dato Cola representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el final y por el principio respectivamente de acuerdo a la política de primero en entrar, primero en salir Tema 4 } Tema 5 } Tema 6 }
  • 126.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 5 Introducción El 8po abstracto de datos Pila Las pilas son abstracciones de datos que organizan una colección de elementos de manera secuencial, donde existe un único punto de interés llamado cima por donde se realizan las operaciones de acceso. La polí6ca de acceso indica que el úl6mo elemento en entrar en una pila es el primero en salir de ella (Last In First Out, LIFO). Una pila es un 6po abstractos de datos que organiza una colección de elementos de forma secuencial. Las operaciones de acceso se realizan por un extremo llamado cima y la polí6ca de acceso es úl6mo en entrar primero en salir (LIFO) Cima Las operaciones de inserción y extracción se realizan por un extremo llamado cima Una pila puede imaginarse como una estructura de datos que dispone los mismos en secuencia uno encima de otros de manera que siempre el último elemento en apilarse es el único que puede ser directamente accedido Pila 1 2 3 4
  • 127.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 6 Interfaz del 6po abstracto de datos Pila La interfaz del 8po abstracto de datos Pila StackIF <T> public interface StackIF<T> extends CollectionIF<T> { /** * Devuelve la cima de la pila. * @return la cima de la pila. */ public T getTop (); /** * Inserta un elemento a la pida. * @param element El elemento a ser añadido. * @return la pila incluyendo el elemento. */ public StackIF<T> push (T element); /** * Extrae de la pila el elemento en la cima. * @return la pila excluyendo la cabeza. */ public StackIF<T> pop (); El interfaz de Pila que u6lizaremos a lo largo de este curso, StackIF está compuesto por las operaciones que describimos a con6nuación cima Todas las operaciones de una pila se atacan por la cima. Este método devuelve el elemento en la cima sin extraerlo 2 3 1 1 Insertar La operación push inserta un elemento encima de la cima de manera que el elemento insertado pasa a ser la nueva cima 2 3 1 2 3 push (1) Extraer La operación pop extrae el elemento en la cima de la pila de manera que el elemento en la cima pasa a ser el de siguiente en la pila 2 3 1 2 3 pop ()
  • 128.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 7 Implementación del 6po abstracto de datos Pila Implementación del 8po abstracto de datos Pila StackIF <T> Existen varias estrategias para implementar pilas que responden al interfaz StackIF anterior. En general, éstas se dividen en implementaciones dinámicas, que ar6culan pilas de capacidad indefinida e implementaciones está6cas, con una capacidad máxima limitada y establecida como parámetro. A con6nuación presentamos varias implementaciones Implementación dinámica basada en elemento y siguiente Según esta estrategia de implementación, una pila está formada por un atributo que representa la cima y otro que es una referencia a una pila y representa el resto de la pila. De esta manera una pila es una colección encadenada de pares (elemento, siguiente) 1 2 3 4 - - Cima y siguiente Cada objeto Pila contiene un atributo para representar el elemento en la cima de la pila y un atributo del tipo definido StackIF que representa una referencia al resto de elementos debajo de la cima Ul8mo, elemento fantasma Aunque en otras implementaciones el valor del último objeto se aprovecha para incluir un último elemento aquí el final se marca con un objeto fantasma con ambos atributos a null. Esto evita excepciones de puntero a null y simplifica la algoritmia con la pila a un único caso base isEmpty () Pila La pila es una secuencia de pares (elemento, siguiente) acabada en un par fantasma
  • 129.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 8 Implementación del 6po abstracto de datos Pila Implementación del 8po abstracto de datos Pila StackIF <T> Existen varias estrategias para implementar pilas que responden al interfaz StackIF anterior. En general, éstas se dividen en implementaciones dinámicas, que ar6culan pilas de capacidad indefinida e implementaciones está6cas, con una capacidad máxima limitada y establecida como parámetro. Implementación está8ca basada en array Según esta estrategia de implementación, una pila está cons6tuida por un array de capacidad limitada y especificada mediante un parámetro y un índice que apunta a la cima de la pila. La pila empieza por la posición 0 y avanza hacia posiciones crecientes 0 0 0 0 3 7 2 3 1 cima Este índice apunta siempre a l e l e m e n t o q u e s e encuentra en la cima de la pila. El índice comienza en 0 y llega hasta capacidad–1 para valores de la pila Extraer Extraer mueve la cima de la pila una posición hacia atrás con lo que la posición anterior pasa a ser la nueva cima. Cima == 0 indica una pila vacía luego esa posición se desaprovecha Insertar Las inserciones mueven la cima una posición hacia adelante e insertan el elemento. Si cima llega a valer capacidad - 1 el array está lleno y no se puede insertar Basura El resto de elementos del array que no pertenecen a la pila son basura, resultado del trabajo con el tipo Capacidad = 10 Pila La pila está formada por los elementos que van desde la posición 0 hasta cima
  • 130.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 9 Implementación del 6po abstracto de datos Pila Implementación del 8po abstracto de datos Pila StackIF <T> Existen varias estrategias para implementar pilas que responden al interfaz StackIF anterior. En general, éstas se dividen en implementaciones dinámicas, que ar6culan pilas de capacidad indefinida e implementaciones está6cas, con una capacidad máxima limitada y establecida como parámetro. Implementación basada en lista Dado que las implementaciones de pilas que hemos visto son bastante similares a las de listas, es posible implementar una pila a par6r de una lista. El carácter está6co o dinámico de la implementación dependerá del 6po de implementación de lista u6lizada 1 2 3 4 5 6 7 8 9 Primero es cima El primer elemento de una lista se corresponde con la cima de la pila Resto es resto de pila El resto de elementos de la lista corresponde con la subpila que hay debajo de la cima Pila La pila se implementa a partir de cualquier implementación del TAD Lista con interfaz ListIF. La operación de insertar se implementa con la inserción en la lista y la de extracción con la operación de obtener resto de la lista ListIF
  • 131.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 10 Algoritmos sobre pilas Algoritmos sobre pilas A diferencia de lo que ocurría en el caso de las listas donde estudiamos que la ordenación era uno de los problemas recurrentes, en el caso de las pilas se considera que tal 6po de manipulaciones no son de interés ya que irían en contra de la esencia organiza6va del 6po – mantener a los elementos dispuestos en el orden de llegada de acuerdo a una polí6ca LIFO. Por ello, en esta sección nos centraremos en discu6r el problema del recorrido de los elementos de una pila y la búsqueda de un elemento dentro de una pila. Algoritmos sobre pilas I. Recorrido El recorrido de los elementos de una pila devuelve un iterador que permite acceder secuencialmente a los mismos según aparecen almacenados en la estructura, en sentido desde la cima hasta la base de la pila. El recorrido en sentido contrario es fácilmente implementable y se deja como ejercicio II. Búsqueda La búsqueda de un elemento sobre los elementos de una pila se realiza de forma secuencial dada la definición del tipo lo que imprime un coste lineal al algoritmo. Si esta operación no fuese una operación interna del tipo dicha búsqueda sería destructiva o requeriría utilizar un iterador (con copia) o reconstruir la estructura tras el algoritmo. La búsqueda como operación interna permite implementar el algoritmo no destructivamente sobre la estructura interna. Independenciadela implementación
  • 132.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 11 Algoritmos sobre pilas Recorrido de los elementos de una pila Para ar6cular el recorrido secuencial de los elementos de una pila debe implementarse el interfaz IteratorIF. Las implementaciones de StackIF anteriores construyen una copia de la pila como manejador para garan6zar que la iteración no modifique el estado del 6po class StackIterator<T> implements IteratorIF<T> { private StackIF<T> handler; private StackIF<T> restart; /** * Constructor para StackIterator. * @param handler el manejador de pilas. */ public StackIterator (StackIF<T> handler) { this.handler = handler; this.restart = new StackDynamic<T> (handler); } /** * Devuelve el siguiente elemento de la iteracion. * @return el siguiente elemento de la iteracion. */ @Override public T getNext () { T top = handler.getTop (); handler.pop (); return top; } Se mantienen 2 manejadores constantemente, uno para articular el recorrido de la pila. El otro siempre apunta a la cima de la pila y se utiliza para implementar la operación de reset del iterador Iteración con reset La operación de avance devuelve el elemento en cima de la pila y actualiza el manejador de recorrido extrayendo la cima. Para invocar esta operación con seguridad hay que asegurarse de que el manejador no apunta a la cola vacía… Avance 2 1 4 3 handler getNext() restart
  • 133.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 12 Algoritmos sobre pilas Recorrido de los elementos de una pila Para ar6cular el recorrido secuencial de los elementos de una pila debe implementarse el interfaz IteratorIF. Las implementaciones de StackIF anteriores construyen una copia de la pila como manejador para garan6zar que la iteración no modifique el estado del 6po /** * Devuelve cierto si existen mas elementos a iterar. * @return cierto si existen mas elementos a iterar. */ @Override public boolean hasNext () { return !handler.isEmpty (); } /** * Restablece el iterador para volver al inicio */ @Override public void reset () { handler = new StackDynamic<T> (restart); } @Override public int hashCode () { ... } @Override public boolean equals (Object o) { ... } @Override public String toString () {...} } Para saber si el iterador contiene más elementos y por tanto puede volver a invocarse la operación de avance o no, hay que preguntar si el manejador ha alcanzado el final de la pila Hay siguiente Una vez que un iterador ha llegado a su fin sólo se puede construir otro iterador, o resetear este a su valor inicial. En este caso sin embargo, la operación de reset requiere una copia con lo que el coste es idéntico al de construir un nuevo iterador. Reset 2 1 4 3 handler reset () restart handler
  • 134.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 13 Algoritmos sobre pilas Búsqueda de un elemento sobre una pila La búsqueda de un dato sobre los elementos contenidos en una pila es un problema de recorrido secuencial que termina cuando se encuentra una cima que corresponde con el dato buscado. El problema es que la búsqueda sobre el 6po es destruc6va a no ser que se aplique sobre la implementación o se u6lice un iterador Búsqueda itera8va con cen8nela /** * Devuelve cierto si la pila contiene el elemento. * @param element El elemento buscado. * @return cierto si la pila contiene el elemento. */ @Override public boolean contains (T element) { IteratorIF<T> stackIt = this.getIterator (); boolean found = false; while (!found && stackIt.hasNext ()) { T anElement = stackIt.getNext (); found = anElement.equals (element); } return found; } En la búsqueda con cen6nela se itera sobre la pila y se u6liza una guarda (cen6nela) para indicar el momento en que se ha encontrado el elemento y la búsqueda puede parar Búsqueda recursiva /** * Devuelve cierto si la lista contiene el elemento. * @param element El elemento buscado. * @return cierto si la lista contiene el elemento. */ @Override public boolean contains (T element) { if (isEmpty ()) return false; return this.element.equals (element) || next.contains (element); } En la búsqueda recursiva se comprueba si la cabeza se corresponde con el elemento buscado. Si es así el algoritmo termina devolviendo cierto y si no, se recurre sobre el resto de la pila para buscar el elemento
  • 135.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 14 Problemas y ejercicios Ejercicios Dado el carácter destruc6vo de las operaciones sobre pilas – para avanzar en una pila es necesario extraer su cima con pop – la realización de muchos de sus algoritmos requiere de un proceso de protección consistente en hacer una copia de la misma. Ignorando el problema de destrucción resuelva los siguientes problemas Diseñe una función que calcule el número de elementos que con6ene una pila I. Longitud de una pila Devolver una lista con los elementos de una pila según aparecen en ésta desde la cima hasta la base II. Pasar a lista Diseñe una función que dada una lista determine si ésta está contenida en una pila como subpila III. Subpila Diseñe una función que devuelva el elemento base de una pila IV. Elemento base Diseñe una función que inserte un dato como elemento en la base de una pila V. Insertar en la base Diseñe una función recursiva que devuelva la pila resultante de concatenar dos pilas VI. Concatenar dos pilas Diseñe una función recursiva que devuelva una pila con los elementos colocados de forma inversa a otra VII. Pila inversa Diseñe una función que devuelva una pila que elimine la primera aparición de un elemento VIII. Borrado de un elemento Diseñe una función que devuelva una pila donde se hayan eliminado todas las apariciones de un elemento IX. Borrar todos Diseñe una función que devuelva una pila con los elementos que preceden a (están encima de) un elemento dado X. Pila prefijo Diseñe una función que devuelva la pila con los elementos que suceden a (están debajo de) un elemento dado XI. Pila sufijo Diseñe una función recursiva que devuelva una pila con todos los elementos mayores a uno dado XII. Pila mayores
  • 136.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 15 Problemas y ejercicios Problemas Las pilas son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de pilas. El juego, en su forma más tradicional, consiste en tres varillas ver6cales. En una de las varillas se apila un número n de discos. Los discos se apilan sobre una varilla en tamaño decreciente. No hay dos discos iguales, y todos ellos están apilados de mayor a menor radio en una de las varillas, quedando las otras dos varillas vacantes. Las torres de Hanoi 1.  Sólo se puede mover un disco cada vez. 2.  Un disco de mayor tamaño no puede descansar sobre uno más pequeño que él mismo. 3.  Sólo puedes desplazar el disco que se encuentre arriba en cada varilla. El juego consiste en pasar todos los discos de la varilla ocupada a una de las otras varillas vacantes. Para realizar este obje6vo, es necesario seguir tres simples reglas:
  • 137.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 16 Problemas y ejercicios Problemas Las pilas son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de pilas. La finalidad del Solitario Carta blanca es mover todas las cartas desde la zona del tablero a las casillas de palo: los cuatro recuadros situados en la parte superior derecha del tablero. Para ganar, el jugador 6ene que hacer cuatro montones de cartas en las casillas, uno por cada palo, y amontonarlas en orden ascendente desde el AS hasta el REY. Puedes mover las cartas de una columna a otra ordenando las cartas de mayor a menor y alternando los La carta blanca colores de los palos, así como u6lizar las casillas libres para apartar cartas de las columnas y así acceder a la carta que hay debajo. La par6da finaliza cuando el jugador ha movido todas las cartas a las casillas de palo o cuando ya no puede realizar ningún movimiento más. Se dice que todas las par6das de Carta blanca pueden ganarse.
  • 138.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 17 Problemas y ejercicios Problemas Las pilas son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de pilas. Aunque actualmente las calculadores permiten operar con expresiones en notación infija, tradicionalmente ha sido frecuente encontrar máquinas que requerían introducir las expresiones en notación posdija. Esto facilita la forma de calculo y evita el uso de paren6zación para desambiguar. De esta manera, 2 + 3 * 5 se expresa en notación posdija como 2 3 + 5 * y debe interpretarse como que a los operandos… Calculadora en notación postfija
  • 139.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 18 Bibliograia BibliograTa Bibliografía básica Estructuras de datos en java. Weiss, Mark Allen. Pearson Addison – Wesley. ISBN 9788478290352
  • 140.
    Tipos abstractos de datos lineales. Pilas Javier Vélez Reyesjvelez@lsi.uned.es5 - 19 Bibliograia BibliograTa Bibliografía complementaria Estructura de datos y algoritmos en java. A. Drozdek. Thomsom. ISBN: 9706866116. 2007 Estructuras de datos con Java. J. Lewis, J. Chase. Pearson – Addison Wesley. ISBN 13: 9788420541914
  • 141.
  • 142.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 2 Índice Índice ›  Introducción ›  Tipos abstractos de datos lineales ›  El tipo abstracto de datos Cola ›  Interfaz del tipo abstracto de datos Cola ›  Implementaciones del tipo abstracto de datos Cola ›  Implementación dinámica ›  Implementación estática ›  Implementación con Lista ›  Algoritmos sobre Colas ›  Recorrido de los elementos de una Cola ›  Búsqueda de un elemento sobre una Cola ›  Problemas y ejercicios ›  Bibliografía
  • 143.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 3 Obje6vos generales Obje8vos ›  Conocer la interfaz del tipo abstracto de datos Cola ›  Aprender a implementar el TAD Cola mediante la interfaz QueueIF ›  En versión estática (con limitación explícita de capacidad máxima) ›  En versión dinámica (sin limitación explícita de capacidad máxima) ›  Utilizando una lista ›  Conocer los principales problemas algorítmicos sobre colas ›  Recorrido de los elementos de una cola ›  Búsqueda de un elemento sobre una cola ›  Practicar el diseño de funciones recursivas sobre cola
  • 144.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 4 Introducción Tipos abstractos de datos lineales Los 6pos abstractos de datos lineales representan abstracciones en las que los datos son organizados de forma secuencial. A con6nuación se muestran los diferentes TADs que caen dentro de esta categoría y que se diferencian, esencialmente, en la forma en que se ofrecen acceso a sus datos Tipos abstractos de datos lineales I. Listas II. Pilas III. Colas El tipo abstracto de datos Lista representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el principio, que puede moverse recursivamente haciendo referencia a otras sublistas El tipo abstracto de dato Pila representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el principio según la política de acceso último en entrar, primero en salir El tipo abstracto de dato Cola representa una estructuras de datos donde los elementos se disponen de forma secuencial y las operaciones de inserción y extracción se aplican por el final y por el principio respectivamente de acuerdo a la política de primero en entrar, primero en salir Tema 4 } Tema 5 } Tema 6 }
  • 145.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 5 Introducción El 8po abstracto de datos Cola Las colas son abstracciones de datos que organizan una colección de elementos de manera secuencial, donde existen dos puntos de interés llamados comienzo y final. Por el comienzo se realizan las operaciones de extracción mientras que por el final se realizan las inserciones. Según esto, la polí6ca de acceso prescribe que el primer elemento en entrar en una cola es el primero en salir de ella (First In First Out, FIFO). Una cola es un 6po abstractos de datos que organiza una colección de elementos de forma secuencial. Las operaciones de extracción se realizan por el principio y las de inserción por el final de acuerdo a la polí6ca de acceso FIFO que prescribe que el primero en entrar es el primero en salir Primero El primero marca el siguiente elemento a extraer. Tras una extracción, primero avanza al siguiente en la cola 1 2 3 4 5 6 7 8 9 Ul8mo El último marca el último elemento que se ha insertado. Tras una inserción, último apunta al elemento insertado
  • 146.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 6 Interfaz del 6po abstracto de datos Cola La interfaz del 8po abstracto de datos Cola QueueIF <T> public interface QueueIF<T> extends CollectionIF<T> { /** * Devuelve la cabeza de la cola. * @return la cabeza de la cola. */ public T getFirst (); /** * Inserta un nuevo elemento a la cola. * @param element El elemento a añadir. * @return la cola incluyendo el elemento. */ public QueueIF<T> enqueue (T element); /** * Borra la cabeza de la cola. * la cola excluyendo la cabeza. */ public QueueIF<T> dequeue (); El interfaz de Cola que u6lizaremos a lo largo de este curso, QueueIF está compuesto por las operaciones que describimos a con6nuación primero Devuelve el elemento que se encuentra en la cabeza de la cola sin extraerlo de la misma. Esta es una operación consultora Insertar La operación add inserta un elemento detrás del último elemento de la cola de manera que este pasa a ser el nuevo último borrar La operación remove extrae el elemento que se encuentra en la cabeza de la cola dejando al siguiente a éste como nueva cabeza 1 2 31 1 2 3 4 1 2 3 4
  • 147.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 7 Implementación del 6po abstracto de datos Cola Implementación del 8po abstracto de datos Cola QueueIF <T> Existen varias estrategias para implementar colas que responden al interfaz QueueIF anterior. En general, éstas se dividen en implementaciones dinámicas, que ar6culan colas de capacidad indefinida e implementaciones está6cas, con una capacidad máxima limitada y establecida como parámetro. A con6nuación presentamos varias implementaciones Implementación dinámica basada en primero y úl8mo Según esta estrategia de implementación, una cola está formada por una cadena de nodos enlazados con referencias al siguiente y dos referencias que apuntan al primer y úl6mo elemento de la cola. La desventaja de esta implementación es que hay que separar la abstracción de la cadena de nodos 1 2 3 4 - primero La referencia al primero se mantiene para saber que elemento extraer en cada paso Datos Los elementos de la cola se representan mediante una estructura de nodos encadenados por referencias al siguiente ul8mo La referencia al último se mantiene para saber detrás de quién se debe hacer la siguiente inserción cola
  • 148.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 8 Implementación del 6po abstracto de datos Cola Implementación del 8po abstracto de datos Cola QueueIF <T> Existen varias estrategias para implementar colas que responden al interfaz QueueIF anterior. En general, éstas se dividen en implementaciones dinámicas, que ar6culan colas de capacidad indefinida e implementaciones está6cas, con una capacidad máxima limitada y establecida como parámetro. A con6nuación presentamos varias implementaciones Implementación está8ca basada en array circular Según esta estrategia de implementación, una cola se almacena en un array de capacidad limitada accedido circularmente mediante dos índices en aritmé6ca modular que apuntan al primer y ul6mo elemento 2 3 0 1 3 7 2 3 4 5 primero El índice primero apunta siempre al elemento en cabeza de la cola. Cuando éste llega al índice máximo del array continua modularmente por 0 Insertar Las inserciones se realizan en la posición último y avanzan el índice último una posición en aritmética modular Capacidad = 10 úl8mo El índice último apunta siempre al primer hueco libre tras el último elemento de la cola. . Cuando éste llega al índice máximo del array continua modularmente por 0 extraer Las extracciones avanzan el índice primero una posición en aritmética modular
  • 149.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 9 Implementación del 6po abstracto de datos Cola Implementación del 8po abstracto de datos Cola QueueIF <T> Existen varias estrategias para implementar colas que responden al interfaz QueueIF anterior. En general, éstas se dividen en implementaciones dinámicas, que ar6culan colas de capacidad indefinida e implementaciones está6cas, con una capacidad máxima limitada y establecida como parámetro. A con6nuación presentamos varias implementaciones Implementación basada en lista Dado que la implementación dinámica de colas que hemos visto es bastante similar a la de listas, es posible implementar una cola a par6r de una lista. El carácter está6co o dinámico de la implementación dependerá del 6po de implementación de lista u6lizada 1 2 3 4 5 6 7 8 9 primero La referencia al primero se mantiene para saber que elemento extraer encada paso ul8mo La referencia al último se mantiene para garantizar una inserción en coste constante ListIF cola
  • 150.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 10 Algoritmos sobre colas Algoritmos sobre colas A diferencia de lo que ocurría en el caso de las listas donde estudiamos que la ordenación era uno de los problemas recurrentes, en el caso de las colas se considera que tal 6po de manipulaciones no son de interés ya que irían en contra de la esencia organiza6va del 6po – mantener a los elementos dispuestos en el orden de llegada de acuerdo a una polí6ca FIFO. Por ello, en esta sección nos centraremos en discu6r el problema del recorrido de los elementos de una cola y la búsqueda de un elemento dentro de una cola. Algoritmos sobre colas I. Recorrido El recorrido de los elementos de una cola devuelve un iterador que permite acceder secuencialmente a los mismos según aparecen almacenados en la estructura, desde el primero hasta el último de la cola. El recorrido en sentido contrario es fácilmente implementable y se deja como ejercicio II. Búsqueda La búsqueda de un elemento sobre los elementos de una cola se realiza de forma secuencial dada la definición del tipo lo que imprime un coste lineal al algoritmo. El problema fundamental en este tipo de algoritmos es que dicha búsqueda es destructiva y requiere o utilizar un iterador (con copia) o reconstruir la estructura tras el algoritmo Independenciadela implementación
  • 151.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 11 Algoritmos sobre colas Recorrido de los elementos de una cola Para ar6cular el recorrido secuencial de los elementos de una cola debe implementarse el interfaz IteratorIF. Las implementaciones de QueueIF anteriores construyen una copia de la cola como manejador para garan6zar que la iteración no modifique el estado del 6po class QueueIterator<T> implements IteratorIF<T> { private QueueIF<T> handler; private QueueIF<T> restart; /** * Constructor para QueueIterator. * @param handler el manejador de colas. */ public QueueIterator (QueueIF<T> handler) { this.handler = handler; this.restart = new QueueDynamic<T> (handler); } /** * Devuelve el siguiente elemento de la iteracion. * @return el siguiente elemento de la iteracion. */ @Override public T getNext () { T element = handler.getFirst (); handler.remove (); return element; } Se mantienen 2 manejadores constantemente, uno para articular el recorrido de la cola. El otro siempre apunta a la cabeza de la cola y se utiliza para implementar la operación de reset del iterador Iteración con reset La operación de avance devuelve el elemento en cabeza de la cola y actualiza el manejador de recorrido extrayendo la cima. Para invocar esta operación con seguridad hay que asegurarse de que el manejador no apunta a la cola vacía… Avance 3 4 1 2 handler getNext() restart
  • 152.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 12 Algoritmos sobre colas Recorrido de los elementos de una cola Para ar6cular el recorrido secuencial de los elementos de una cola debe implementarse el interfaz IteratorIF. Las implementaciones de QueueIF anteriores construyen una copia de la cola como manejador para garan6zar que la iteración no modifique el estado del 6po /** * Devuelve cierto si existen mas elementos a iterar. * @return cierto si existen mas elementos a iterar. */ @Override public boolean hasNext () { return !handler.isEmpty (); } /** * Restablece el iterador para volver iterar. */ @Override public void reset () { handler = new QueueDynamic<T> (restart); } } Para saber si el iterador contiene más elementos y por tanto puede volver a invocarse la operación de avance o no, hay que preguntar si el manejador ha alcanzado el final de la cola Hay siguiente Una vez que un iterador ha llegado a su fin sólo se puede construir otro iterador, o resetear éste a su valor inicial. En este caso sin embargo, la operación de reset requiere una copia con lo que el coste es idéntico al de construir un nuevo iterador. Reset 3 4 1 2 handler reset() restart handler
  • 153.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 13 Algoritmos sobre colas Búsqueda de un elemento sobre una cola La búsqueda de un dato sobre los elementos contenidos en una cola es un problema de recorrido secuencial que termina cuando se encuentra una cabeza que corresponde con el dato buscado. Dado que el 6po no 6ene una definición recursiva, el problema de búsqueda no se presta a este 6po de resolución algorítmica. A con6nuación presentamos dos versiones de la búsqueda itera6va con cen6nela que aprovechan la estructura interna de la implementación del 6po Búsqueda en QueueDynamic @Override public boolean contains (T element){ boolean found = false; Node<T> node = first; while (!found && node != null) { found = node.getElement ().equals (element); node = node.getNext (); } return found; } Es esta implementación se realiza una búsqueda con cen6nela sobre la estructura de nodos enlazados que implementar el 6po cola Búsqueda en QueueSta8c @Override public boolean contains (T element) { boolean found = false; int index = first; while (!found && Math.abs (last - index) > 0) { found = elements [index].equals (element); index = next (index); } return found; } En la implementación está6ca los datos son almacenados sobre una estructura vectorial que debe ser recorrida circularmente desde el primero hasta el úl6mo elemento, si el cen6nela no lo impide
  • 154.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 14 Problemas y ejercicios Ejercicios Dado el carácter destruc6vo de las operaciones sobre colas – para avanzar en una cola es necesario extraer su cabeza con invocando a remove – la realización de muchos de sus algoritmos requiere de un proceso de protección consistente en hacer una copia de la misma. Ignorando el problema de destrucción resuelva los siguientes problemas Diseñe una función que calcule el número de elementos que con6ene una cola I. Longitud de una cola Devolver una lista con los elementos de una cola según aparecen en ésta desde el primero al úl6mo II. Pasar a lista Diseñe una función que dada una cola determine si es subcola de otra dada de mayor tamaño III. Subcola Función que extrae los números pares de una cola de enteros. Repita el ejercicio para extraer los de posición par en la cola IV. Extraer pares Diseñe una función que inserte en una cola de enteros los elementos de forma ordenada crecientemente V. Insertar en orden Diseñe una función recursiva que devuelve la cola resultante de concatenar dos colas VI. Concatenar dos colas Diseñe una función recursiva que devuelva una cola con los elementos colocados de forma inversa a otra VII. Cola inversa Diseñe una función que devuelva una cola que elimine la primera aparición de un elemento VIII. Borrado de un elemento Diseñe una función que devuelva una cola donde se hayan eliminado todas las apariciones de un elemento IX. Borrar todos Diseñe una función que devuelva una cola con los elementos que preceden a un elemento dado X. Cola prefijo Diseñe una función que devuelva la cola sufijo que sucede a un elemento dado XI. Cola sufijo Diseñe una función recursiva que devuelva una cola con todos los elementos mayores a uno dado XII. Cola mayores
  • 155.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 15 Problemas y ejercicios Problemas Las colas son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de colas. Diferentes procesos de un sistema opera6vo compiten en ejecución por adquirir el uso de una impresora que esta a su vez conectada a varios equipos dispuestos en una red de área local. La cola de impresión es una abstracción donde se encolan los procesos a la espera de ser atendidos por el servidor de impresión Competición de procesos por un recurso Competición de procesos por un recurso En escenarios concurrentes los procesos productores deben comunicarse con los consumidores de información. Dado que el ritmo de trabajo de unos y otros no es el mismo se u6lizan colas de almacenamiento de mensajes como mecanismo de amor6guación
  • 156.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 16 Problemas y ejercicios Problemas Las colas son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de colas. En las redes de computadoras los disposi6vos de interconexión u6lizan colas para almacenar la información entrante y entregarla a sus des6natarios al ritmo que ellos requieran. Asimismo se u6liza esta técnica para realizan propagación en broadcast o mul6cast Enrutamiento de paquetes IP Computación distribuida En computación distribuida se u6lizan sistemas de mensajería encargados de mover la información. En comunicación punto a punto las colas se u6lizan para persis6r los mensajes y garan6zar la entrega. En comunicación de eventos varios procesos se registran como escuchadores de una cola donde otros se publican eventos de un determinado tópico
  • 157.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 17 Bibliograba BibliograTa Bibliografía básica Estructuras de datos en java. Weiss, Mark Allen. Pearson Addison – Wesley. ISBN 9788478290352
  • 158.
    Tipos abstractos de datos lineales. Colas Javier Vélez Reyesjvelez@lsi.uned.es6 - 18 Bibliograba BibliograTa Bibliografía complementaria Estructura de datos y algoritmos en java. A. Drozdek. Thomsom. ISBN: 9706866116. 2007 Estructuras de datos con Java. J. Lewis, J. Chase. Pearson – Addison Wesley. ISBN 13: 9788420541914
  • 159.
  • 160.
  • 161.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 2 Índice Índice ›  Introducción ›  Tipos abstractos de datos jerárquicos ›  El tipo abstracto de datos Árbol general ›  Interfaz del tipo abstracto de datos Árbol general ›  Implementaciones del tipo abstracto de datos Árbol general ›  Implementación dinámica ›  Implementación estática con array de posiciones variables ›  Algoritmos sobre Árboles generales ›  Recorrido de los elementos de un Árbol general ›  Búsqueda de un elemento sobre una Árboles general ›  Problemas y ejercicios ›  Bibliografía
  • 162.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 3 Obje6vos generales Obje8vos ›  Conocer la interfaz del tipo abstracto de datos Árbol general ›  Aprender a implementar el TAD Árbol general mediante la interfaz TreeIF ›  En versión estática (con limitación explícita de capacidad máxima) ›  En versión dinámica (sin limitación explícita de capacidad máxima) ›  Conocer los principales problemas algorítmicos sobre árboles generales ›  Recorrido de los elementos de un árboles generales ›  Búsqueda de un elemento sobre un árboles generales ›  Practicar el diseño de funciones recursivas sobre árboles generales
  • 163.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 4 Introducción Tipos abstractos de datos jerárquicos Los 6pos abstractos de datos jerárquicos representan abstracciones en las que los datos se distribuyen a través de relaciones de parento-filialidad donde cada elemento 6ene un padre y varios hijos. En función del número máximo de hijos que puede tener un elemento dis6nguiremos entre árboles binarios (con 2 hijos como máximo) y árboles generales (sin limitación en el número de hijos). Aunque los segundos pueden considerarse una generalización de los primeros, ambos presentan implementaciones y escenarios de uso diferentes lo que jus6fica su consideración como 6pos dis6ntos Tipos abstractos de datos lineales I. Árboles generales II. Árboles binarios Un árbol binario es un tipo especial de árbol donde cada elemento del mismo puede referenciar a lo sumo a 2 hijos. Este tipo de estructuras se utilizan frecuentemente para representar en computación no sólo conjuntos de datos con una relación de dependencia padre-hijo sino también para articular esquemas de búsqueda eficientes Los árboles generales pueden considerarse a todos los efectos una generalización de los árboles binarios donde el número de hijos está limitado por una constante k > 2 (o no existe limitación en el número de hijos). Aunque, en principio, es posible expresar todo árbol general como un árbol binario, existen situaciones en computación donde este tipo de abstracciones tiene usos interesantes Tema 7 } Tema 8 }
  • 164.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 5 Introducción El 8po abstracto de datos Árbol general Un árbol general es una estructura que organiza una colección de elementos a través de una relación de parento-filialidad donde cada elemento dispone a lo sumo de un padre y de un número de hijos no prefijado . Si un elemento no 6ene padre se llama nodo raíz. En un árbol general hay siempre un y sólo un elemento raíz. Si un elemento no 6ene hijos se llama elemento hoja. La definición computable del 6po se establece recursivamente de la siguiente manera Un árbol general es un 6po abstracto de datos que da acceso directo a un elemento llamado raíz y, a un número indeterminado de subárboles que dependen jerárquicamente de él como hijos Subárboles Los árboles generales pueden tener cualquier número de hijos 0 1 7 2 4 8 9 3 5 6 Elemento hoja Cuando un elemento no tiene hijos se llama hoja Raíz La raíz es el elemento del que cuelga el resto de nodos Niveles El número de niveles de un árbol indica la separación máxima que hay entre la raíz y la hoja más alejada de ésta medida en número de arcos
  • 165.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 6 Interfaz del 6po abstracto de datos Árbol general La interfaz del 8po abstracto de datos Árbol general TreeIF <T> public interface TreeIF <T> { public int PREORDER = 0; public int POSTORDER = 1; public int LRBREADTH = 2; public int RLBREADTH = 3; /** * Devuelve el elemento raiz del arbol. * @return el elemento raiz del arbol. */ public T getRoot (); /** * Establece el elemento raiz. * @param element El elemento a establecer. */ public void setRoot (T element); /** * Devuelve el primer los hijos de un arbol. * @return los hijos de un arbol. */ public ListIF <TreeIF <T>> getChildren (); /** * Devuelve el hijo en posición pos. * @param pos La posición con base en 1. */ public void getChild (int pos); El interfaz de Árbol general que u6lizaremos a lo largo de este curso, TreeIF está compuesto por las operaciones que describimos a con6nuación Recorridos Estas constantes sirven para identificar en el método getIterator distintas estrategias de recorrido de los elementos del árbol Obtener raíz Devuelve la raíz del árbol. Este método devuelve un elemento de tipo T distinto de nulo Establecer raíz Esta operación establece el valor asignado a la raíz de un del árbol. Si el valor es null la operación no tiene efecto Obtener hijos Esta operación consultora devuelve la lista de todos los subárboles que son hijos del nodo en curso 1 0 Obtener hijo Esta operación consultora devuelve el subárbol que corresponde con el hijo ubicado en la posición pos
  • 166.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 7 Interfaz del 6po abstracto de datos Árbol general La interfaz del 8po abstracto de datos Árbol general TreeIF <T> /** * Devuelve el elemento raiz del arbol. * @return el elemento raiz del arbol. */ public T addChild (TreeIF<T> child); /** * Extrae un subarbol como hijo. * @param index el indice del subarbol con base en 0. */ public void removeChild (int index); /** * Devuelce cierto si el arbol es un nodo hoja. * @return cierto si el arbol es un nodo hoja. */ public boolean isLeaf (); /** * Devuelve un iterador para la lista. * @param traversalType El tipo de recorrido. * @return un iterador para la lista. */ public IteratorIF<T> getIterator (int traversalType); El interfaz de Árbol general que u6lizaremos a lo largo de este curso, TreeIF está compuesto por las operaciones que describimos a con6nuación Añadir nuevo hijo A través de esta operación se puede añadir un nuevo subárbol como hijo más a la derecha en la colección de hijos Eliminar hijo A través de esta operación se borra el hijo en la posición indicada por index en la colección Es hoja Esta operación consultora indica si el nodo en curso es un nodo hoja o no lo es Recorrido Esta operación devuelve un iterador que permite acceder a todos los elementos del árbol 2 false true 1,2,3,4
  • 167.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 8 Implementación del 6po abstracto de datos Árbol general Implementación del 8po abstracto de datos Árbol general TreeIF <T> Existen varias estrategias de implementación de árboles generales que responden al interfaz TreeIF. Éstas se dividen en implementaciones dinámicas, con capacidad indefinida para almacenar elementos e implementaciones está6cas, con una capacidad máxima limitada establecida por parámetro. A con6nuación presentamos varias implementaciones Implementación dinámica basada en cola de hijos Según esta estrategia de implementación, un árbol es un objeto que representa el nodo raíz del mismo. Cada nodo 6ene un atributo para almacenar el valor del elemento y una cola de árboles que con6enen referencias a los hijos Elemento Almacena el valor del dato en el nodo 1 2 5 e Hijos Lista de referencias a subárboles hijo - 3 - 3 - 8 7 - 9 -
  • 168.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 9 Implementación del 6po abstracto de datos Árbol general Implementación del 8po abstracto de datos Árbol general TreeIF <T> Implementación está8ca mediante array de posiciones hijas variables En esta implementación un árbol se representa como un array de nodos. El valor del nodo raíz se encuentra en la posición 0. Cada nodo 6ene el valor del elemento que porta y la lista de índices que indican las posiciones dentro del array donde están los nodos hijos Capacidad máxima y longitud La capacidad se expresa en número de nodos 8 9 6 7 4 5 2 3 0 1 Existen varias estrategias de implementación árboles generales que responden al interfaz TreeIF anterior. Éstas se dividen en implementaciones dinámicas, con capacidad indefinida para almacenar elementos e implementaciones está6cas, con una capacidad máxima limitada establecida por parámetro. A con6nuación presentamos varias implementaciones 0 3 5 6 1 9 4 4 7 7 2 1 8 9 2 5 6 3 8
  • 169.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 10 Algoritmos sobre árboles generales Algoritmos sobre árboles generales Como viene siendo frecuente a lo largo de este curso, los tres 6pos de algoritmos canónicos aplicables a cualquier estructura de datos son recorrido, búsqueda y ordenación. En este caso, la ordenación debe entenderse como una reorganización de los nodos del árbol para favorecer algún criterio (^picamente la búsqueda). Sin embargo, no estudiaremos ningún algoritmo de ordenación y nos centraremos sólo en recorridos y búsquedas Algoritmos sobre árboles generales I. Recorrido El recorrido de los elementos de un árbol general devuelve un iterador que permite acceder secuencialmente a los mismos según aparecen almacenados en la estructura. Sin embargo, existen distintos criterios de secuenciamiento que pueden aplicarse para construir un recorrido. Aquí estudiaremos los más típicamente aplicados II. Búsqueda La búsqueda de un elemento sobre los nodos de un árbol general se realiza de forma recursiva dada la definición del tipo lo que imprime un coste lineal al algoritmo en el peor caso. La ventaja de este tipo de algoritmos, con respecto a sus equivalentes en otras estructuras de datos es que el proceso no es destructivo con lo que no se requiere utilizar un iterador (con copia) ni reconstruir la estructura tras la aplicación del algoritmo Independenciadela implementación
  • 170.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 11 Algoritmos sobre árboles generales Recorrido de los elementos de un árbol general Los recorridos que pueden aplicarse sobre las estructuras arborescentes son varios en función de la estrategia de secuenciamiento que se aplique sobre los elementos del 6po abstracto de datos. En concreto es posible dis6nguir 4 estrategias organizados de la siguiente manera Recorridos sobreárboles I. Recorridos en profundidad Se recorre el árbol recursivamente en profundidad. En función de donde se aloje, relativamente cada nodo con respecto a sus hijos se distinguen 2 recorridos II. Recorridos en anchura Preorden Postorden Cada nodo se inserta antes de l a c o l e c c i ó n d e n o d o s c o r r e s p o n d i e n t e a s u s descendentes Cada nodo se inserta detrás de l a c o l e c c i ó n d e n o d o s c o r r e s p o n d i e n t e a s u s descendentes S A C O C A O S Se recorre el árbol en anchura colocando primero todos los elementos del nivel k antes de pasar a colocar los del nivel k + 1. En función del orden en que se disponen los elementos por niveles se distinguen dos recorridos en anchura Anchura Anchura inversa Se disponen los elementos del árbol por niveles de izquierda a derecha y desde la raíz a las hojas Se disponen los elementos de forma inversa a como establece un recorrido en anchura O C A S S A C O
  • 171.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 12 Algoritmos sobre árboles generales Recorrido de los elementos de una árbol general Para implementar el iterador de los árboles generales u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola public class TreeIterator<T> implements IteratorIF<T> { private IteratorIF<T> iterator; /** * Constructor para TreeIterator. * @param handler el manejador de arboles. * @param type el tipo de recorrido. */ public TreeIterator (TreeIF<T> handler, int type) { QueueIF<T> traverse = null; switch (type) { case TreeIF.PREORDER: traverse = preorder (handler); break; case TreeIF.POSTORDER: traverse = postorder (handler); break; case TreeIF.LRBREADTH: traverse = lrBreadth (handler); break; case TreeIF.RLBREADTH: traverse = rlBreadth (handler); break; } this.iterator = new QueueIterator<T> (traverse); } /** * Devuelve el siguiente elemento de la iteracion. * @return el siguiente elemento de la iteracion. */ @Override public T getNext () { return iterator.getNext (); } La iteración de los elementos del árbol se delega en el iterador de cola que es construido en el constructor. La función de reset está garantizada Iteración con reset La función de avance delega en el iterador de cola que se ha construido previamente. Esta aproximación simplifica las operaciones pero penaliza el tiempo de la construcción del iterador Avance Construcción En función del valor del parámetro del tipo de recorrido, el constructor invoca a una u otra función privada que devuelve una cola con los elementos dispuestos en el orden apropiado. Después se construye un iterador sobre la cola resultante
  • 172.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 13 Algoritmos sobre árboles generales /** * Devuelve cierto si existen mas elementos en el iterador. * @return cierto si existen mas elementos en el iterador. */ @Override public boolean hasNext () { return iterator.hasNext (); } /** * Restablece el iterador para volver a recorrer la estructura. */ @Override public void reset () { iterator.reset (); } private QueueIF<T> preorder (TreeIF<T> tree) { QueueIF<T> traverse = new QueueDynamic<T> (); T element = tree.getRoot (); traverse.add (element); IteratorIF <TreeIF <T>> childrenIt = tree.getChildren ().getIterator (); while (childrenIt.hasNext ()) { TreeIF <T> aChild = childrenIt.getNext (); QueueIF <T> aTraverse = preorder (aChild); addAll (traverse, aTraverse); } return traverse; } La función de siguiente se delega sobre el iterador de cola. Habrá siguientes elementos que visitar si el iterador de cola aún no ha finalizado Siguiente El recorrido en preorden inserta primero en la cola cada nodo y luego construye recursivamente las colas de los subárboles hijos. Mediante el método addAll dichas colas se añaden, en ese orden a la cola principal. Preorden Reset La función de restablecimiento del iterador se delega igualmente sobre el método homónimo del iterador de colas Recorrido de los elementos de una árbol general Para implementar el iterador de los árboles generales u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola
  • 173.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 14 Algoritmos sobre árboles generales private QueueIF<T> postorder (TreeIF<T> tree) { QueueIF<T> traverse = new QueueDynamic<T> (); T element = tree.getRoot (); IteratorIF <TreeIF <T>> childrenIt = tree.getChildren ().getIterator (); while (childrenIt.hasNext ()) { TreeIF <T> aChild = childrenIt.getNext (); QueueIF <T> aTraverse = postorder (aChild); addAll (traverse, aTraverse); } traverse.add (element); return traverse; } private QueueIF<T> lrBreadth (TreeIF<T> tree) { QueueIF<T> traverse = new QueueDynamic <T> (); QueueIF<TreeIF<T>> aux = new QueueDynamic <TreeIF<T>> (); aux.add (tree); while (!aux.isEmpty ()) { TreeIF<T> aTree = aux.getFirst (); T element = aTree.getRoot (); IteratorIF <TreeIF <T>> childrenIt = aTree.getChildren ().getIterator (); while (childrenIt.hasNext ()) { TreeIF <T> aChild = childrenIt.getNext (); aux.add (aChild); } traverse.add (element); aux.remove (); } return traverse; } El recorrido en postorden inserta primero los elementos de los subárboles hijos y después anexa el nodo en curso. Postorden El recorrido en anchura utiliza dos colas para su construcción. En una se van insertando los elementos resultantes del recorrido. La otra es una cola auxiliar que sirve para almacenar los subárboles pendientes de ser procesados en cada paso Anchura Recorrido de los elementos de una árbol general Para implementar el iterador de los árboles generales u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola
  • 174.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 15 Algoritmos sobre árboles generales private QueueIF<T> rlBreadth (TreeIF<T> tree) { QueueIF<T> traverse = lrBreadth (tree); StackIF<T> aux = new StackDynamic<T> (); while (!traverse.isEmpty ()) { T element = traverse.getFirst (); aux.push (element); traverse.remove (); } while (!aux.isEmpty ()) { T element = aux.getTop (); traverse.add (element); aux.pop (); } return traverse; } private void addAll (QueueIF<T> q, QueueIF<T> p) { while (!p.isEmpty ()) { T element = p.getFirst (); q.add (element); p.remove (); } } } La anchura inversa es el recorrido inverso al anterior por tanto la implementación más sencilla consiste en generar un recorrido en anchura e invertirlo posteriormente. Para ello se utiliza una pila. Primero se mueven los elementos de la cola resultante a una pila. Después se extraen de la cola para insertarlos en una pilla. Finalmente se extraen de la pila para insertarlos nuevamente en la cola Anchura inversa La función addAll inserta en una cola todos los elementos de una segunda cola Encolar todos Recorrido de los elementos de una árbol general Para implementar el iterador de los árboles generales u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola
  • 175.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 16 Algoritmos sobre árboles generales Búsqueda de un elemento sobre un árbol general La búsqueda de un dato sobre los elementos contenidos en un árbol general es un problema de recorrido que termina cuando se encuentra el elemento buscado dentro de la estructura de datos. Dado que se trata de un 6po con definición recursiva el algoritmo será esencialmente iterar sobre cada hijo para aplicar sobre él recursivamente el algoritmo Búsqueda recursiva iterada public boolean contains (T element) { if (this.element.equals (element)) return true; else { IteratorIF <TreeIF <T>> childrenIt = children.getIterator (); boolean found = false; while (!found && childrenIt.hasNext ()) { TreeIF <T> aChild = childrenIt.getNext (); found = aChild.contains (element); } return found; } } Como puede apreciarse este algoritmo es agnós6co de la estructura de implementación subyacente ya que se apoya en operaciones definidas en el interfaz de árbol general TreeIF. En primer lugar, se comprueba si el nodo raiz coincide con el elemento buscado. Si es así, hemos terminado. Si no, debemos iterar sobre cada uno de los hijos realizando una búsqueda con cen6nela en la colección de hijos pero recursiva en cada hijo
  • 176.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 17 Problemas y ejercicios Ejercicios Pueden encontrarse mul6tud de situaciones donde es necesario manipular la estructura interna de los elementos de un árbol general. A con6nuación presentamos algunos ejercicios que vienen a ejemplificar tales situaciones Diseñe una función devuelva el número de elementos que con6ene un árbol general I. Contar elementos Diseñe una función que devuelve la suma de todos los elementos de un árbol general de enteros II. Sumar elementos Diseñe una función recursiva que devuelva una lista con todos los elementos pares de un árbol de enteros III. Encontrar pares Diseñe una función recursiva que dado un árbol de enteros devuelva otro árbol solamente con los elementos pares IV. Eliminar impares Diseñe una función dado un árbol de enteros mul6plique el valor en cada nodo por su altura V. Alturas Diseñe una función recursiva que determine si dos árboles generales son estructuralmente idén6cos VI. Comparación de árboles Diseñe una función recursiva que indique si dos árboles son la imagen especular el uno del otro VII. Imagen especular Diseñe una función que dado un árbol general de enteros sus6tuya el valor en cada nodo por el valor acumulado de todos los nodos anteriores a el en un recorrido en profundidad VIII. Sumar anteriores
  • 177.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 18 Problemas y ejercicios Problemas Los árboles generales son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de este 6po abstracto de datos. Una cola de prioridad es un 6po especial de cola donde las inserciones se realizan por orden de acuerdo a un criterio compara6vo entre los elementos de la cola. La implementación más eficiente se realiza con árboles generales donde en el nivel k están los elementos de prioridad k Colas de prioridad Árboles de decisión En inteligencia ar6ficial y minería de datos se u6lizan árboles de decisión para representar problemas de decisión. Cada nodo representa un criterio de decisión y las ramas de éste las posibles alterna6vas
  • 178.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 19 Problemas y ejercicios Problemas Los datos almacenados en una base de datos suelen mantenerse ges6onados mediante estructuras arbóreas complejas de un nivel fijo de profundidad (nivel raiz, nivel de página, nivel de hoja y nivel de registro, etc.) Bases de datos Juegos La inteligencia ar6ficial de muchos juegos de estrategia, como el ajedrez o las tres en ralla, u6liza árboles para representar el espacio de búsqueda de las alterna6vas de movimiento dentro del juego valorando con una función de u6lidad el beneficio, posi6vo o nega6vo, de realizarlo. Una función umbral permite tomar la decisión Las árboles generales son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de este 6po abstracto de datos.
  • 179.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 20 Bibliograca BibliograTa Bibliografía básica Estructuras de datos en java. Weiss, Mark Allen. Pearson Addison – Wesley. ISBN 9788478290352
  • 180.
    Tipos abstractos de datos jerárquicos. Árboles generales Javier Vélez Reyesjvelez@lsi.uned.es7 - 21 Bibliograca BibliograTa Bibliografía complementaria Estructura de datos y algoritmos en java. A. Drozdek. Thomsom. ISBN: 9706866116. 2007 Estructuras de datos con Java. J. Lewis, J. Chase. Pearson – Addison Wesley. ISBN 13: 9788420541914
  • 181.
  • 182.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 2 Índice Índice ›  Introducción ›  Tipos abstractos de datos jerárquicos ›  El tipo abstracto de datos Árbol binario ›  Interfaz del tipo abstracto de datos Árbol binario ›  Implementaciones del tipo abstracto de datos Árbol binario ›  Implementación dinámica ›  Implementación estática con array de posiciones fijas ›  Implementación estática con array de posiciones variables ›  Algoritmos sobre Árboles binarios ›  Recorrido de los elementos de un Árbol binario ›  Búsqueda de un elemento sobre una Árboles binarios ›  Ordenación y Equilibrado en Árboles binarios ›  Problemas y ejercicios ›  Bibliografía
  • 183.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 3 Obje6vos generales Obje8vos ›  Conocer la interfaz del tipo abstracto de datos Árbol binario ›  Aprender a implementar el TAD Árbol binario mediante la interfaz BTreeIF ›  En versión estática (con limitación explícita de capacidad máxima) ›  En versión dinámica (sin limitación explícita de capacidad máxima) ›  Conocer los principales problemas algorítmicos sobre árboles binarios ›  Recorrido de los elementos de un árboles binarios ›  Búsqueda de un elemento sobre un árboles binarios ›  Ordenación y equilibrado de un árboles binarios ›  Practicar el diseño de funciones recursivas sobre árboles binarios
  • 184.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 4 Introducción Tipos abstractos de datos jerárquicos Los 6pos abstractos de datos jerárquicos representan abstracciones en las que los datos se distribuyen a través de relaciones de parento-filialidad donde cada elemento 6ene un padre y varios hijos. En función del número máximo de hijos que puede tener un elemento dis6nguiremos entre árboles binarios (con 2 hijos como máximo) y árboles generales (sin limitación en el número de hijos). Aunque los segundos pueden considerarse una generalización de los primeros, ambos presentan implementaciones y escenarios de uso diferentes lo que jus6fica su consideración como 6pos dis6ntos Tipos abstractos de datos lineales I. Árboles generales II. Árboles binarios Un árbol binario es un tipo especial de árbol donde cada elemento del mismo puede referenciar a lo sumo a 2 hijos. Este tipo de estructuras se utilizan frecuentemente para representar en computación no sólo conjuntos de datos con una relación de dependencia padre-hijo sino también para articular esquemas de búsqueda eficientes Los árboles generales pueden considerarse a todos los efectos una generalización de los árboles binarios donde el número de hijos está limitado por una constante k > 2 (o no existe limitación en el número de hijos). Aunque, en principio, es posible expresar todo árbol general como un árbol binario, existen situaciones en computación donde este tipo de abstracciones tiene usos interesantes Tema 7 } Tema 8 }
  • 185.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 5 Introducción El 8po abstracto de datos Árbol binario Un árbol binario es una estructura que organiza una colección de elementos a través de una relación de parento-filialidad donde cada elemento dispone a lo sumo de un padre y a lo sumo de 2 hijos. Si un elemento no 6ene padre se llama nodo raíz. En un árbol binario hay siempre un y sólo un elemento raíz. Si un elemento no 6ene hijos se llama elemento hoja. La definición computable del 6po se establece recursivamente de la siguiente manera Un árbol binario es un 6po abstracto de datos que da acceso directo a un elemento llamado raíz y, a lo sumo, a dos subárboles que dependen jerárquicamente de él como hijos llamados subárbol izquierdo y subárbol derecho Árbol binario Los árboles binarios pueden tener a lo sumo dos elementos hijos 0 1 7 2 4 8 9 3 5 6 Elemento hoja Cuando un elemento no tiene hijos se llama hoja Raíz La raíz es el elemento del que cuelga el resto de nodos Niveles El número de niveles de un árbol indica la separación máxima que hay entre la raíz y la hoja más alejada de ésta medida en número de arcos
  • 186.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 6 Interfaz del 6po abstracto de datos Árbol binario La interfaz del 8po abstracto de datos Árbol binario BTreeIF <T> public interface BTreeIF <T> { public int PREORDER = 0; public int INORDER = 1; public int POSTORDER = 2; public int LRBREADTH = 3; public int RLBREADTH = 4; /** * Devuelve el elemento raiz del arbol. * @return el elemento raiz del arbol. */ public T getRoot (); /** * Devuelve el subarbol izquierdo o null si no existe. * @return el subarbol izquierdo. */ public BTreeIF <T> getLeftChild (); /** * Devuelve el subarbol derecho o null si no existe. * @return el subarbol derecho. */ public BTreeIF <T> getRightChild (); El interfaz de Árbol binario que u6lizaremos a lo largo de este curso, BTreeIF está compuesto por las operaciones que describimos a con6nuación Recorridos Estas constantes sirven para identificar en el método getIterator distintas estrategias de recorrido de los elementos del árbol Obtener raíz Devuelve la raíz del árbol. Este método devuelve un elemento de tipo T distinto de nulo Obtener hijo izquierdo Esta operación consultora devuelve el subárbol que cuelga como hijo izquierdo del árbol sobre el que se consulta Obtener hijo derecho Esta operación consultora devuelve el subárbol que cuelga como hijo derecho del árbol sobre el que se consulta 1
  • 187.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 7 Interfaz del 6po abstracto de datos Árbol binario La interfaz del 8po abstracto de datos Árbol binario BTreeIF <T> /** * Establece el elemento raiz. * @param element El elemento a establecer. */ public void setRoot (T element); /** * Establece el subarbol izquierdo. * @param tree el arbol a esablecer. */ public void setLeftChild (BTreeIF <T> tree); /** * Establece el subarbol derecho. * @param tree el arbol a esablecer. */ public void setRightChild (BTreeIF <T> tree); /** * Borra el subarbol izquierdo. */ public void removeLeftChild (); /** * Borra el subarbol derecho. */ public void removeRightChild (); El interfaz de Árbol binario que u6lizaremos a lo largo de este curso, BTreeIF está compuesto por las operaciones que describimos a con6nuación Asignar elemento raíz A través de esta operación se puede modificar el valor del elemento raíz del árbol referido Asignar hijo izquierdo A través de esta operación se cambia el subárbol izquierdo por otro subárbol pasado como parámetro Asignar hijo izquierdo A través de esta operación se cambia el subárbol izquierdo por otro subárbol pasado como parámetro Eliminar hijo izquierdo Esta operación elimina el subárbol izquierdo. Si no existe hijo derecho se convierte en hoja 4 Eliminar hijo derecho Esta operación elimina el subárbol derecho. Si no existe hijo izquierdo se convierte en hoja
  • 188.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 8 Interfaz del 6po abstracto de datos Árbol binario La interfaz del 8po abstracto de datos Árbol binario BTreeIF <T> /** * Devuelce cierto si el arbol es un nodo hoja. * @return cierto si el arbol es un nodo hoja. */ public boolean isLeaf (); /** * Devuelve cierto si el arbol es vacio. * @return cierto si el arbol es vacio. */ public boolean isEmpty (); } El interfaz de Árbol binario que u6lizaremos a lo largo de este curso, BTreeIF está compuesto por las operaciones que describimos a con6nuación Es hoja Este predicado determina si el elemento de un árbol es un elemento hoja o no Recorrido Devuelve un iterador que permite recorrer los elementos del árbol. Los tipos de recorridos (ver principio) son preorden, inorden, postorden, anchura y anchura inversa falso cierto 2,1,3 inorden
  • 189.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 9 Implementación del 6po abstracto de datos Árbol binario Implementación del 8po abstracto de datos Árbol binario BTreeIF <T> Existen varias estrategias de implementación árboles binarios que responden al interfaz BTreeIF anterior. Éstas se dividen en implementaciones dinámicas, con capacidad indefinida para almacenar elementos e implementaciones está6cas, con una capacidad máxima limitada establecida por parámetro. A con6nuación presentamos varias implementaciones Implementación dinámica basada en enlaces izquierdo y derecho Según esta estrategia de implementación, un árbol es un objeto que representa el nodo raíz del mismo. Cada nodo 6ene un atributo para almacenar el valor del elemento y dos atributos de 6po árbol binario para referenciar a los subárboles izquierdo y derecho Elemento Almacena el valor del dato en el nodo 1 2 - 5 - - 3 - - 4 - - 6 e Izquierdo Referencia al hijo izquierdo Derecho Referencia al hijo derecho
  • 190.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 10 Implementación del 6po abstracto de datos Árbol binario Implementación del 8po abstracto de datos Árbol binario BTreeIF <T> Existen varias estrategias de implementación árboles binarios que responden al interfaz BTreeIF anterior. Éstas se dividen en implementaciones dinámicas, con capacidad indefinida para almacenar elementos e implementaciones está6cas, con una capacidad máxima limitada establecida por parámetro. A con6nuación presentamos varias implementaciones Implementación está8ca mediante array de posiciones hijas fijas En esta implementación un árbol se representa como un array de elementos. El valor del elemento raíz se encuentra en la posición 0. Para el elemento en la posición i, su hijo izquierdo, si hay, estará en la posición 2*i+1 y su hijo derecho en la posición 2*i+2 Niveles = 4 Capacidad máxima y longitud La capacidad de esta implementación se expresa en términos del número máximo de niveles. Si n es el número máximo de niveles hace falta un vector de tamaño 2n+1. El árbol debe estar equilibrado y casi completo para un aprovechamiento eficiente - 59 34 87 20 1 6 - - - - 8 9 6 7 4 5 2 3 0 1 0 1 2 3 4 1 0 izquierdo derecho
  • 191.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 11 Implementación del 6po abstracto de datos Árbol binario Implementación del 8po abstracto de datos Árbol binario BTreeIF <T> Existen varias estrategias de implementación árboles binarios que responden al interfaz BTreeIF anterior. Éstas se dividen en implementaciones dinámicas, con capacidad indefinida para almacenar elementos e implementaciones está6cas, con una capacidad máxima limitada establecida por parámetro. A con6nuación presentamos varias implementaciones Implementación está8ca mediante array de posiciones hijas variables En esta implementación un árbol se representa como un array de nodos. El valor del nodo raíz se encuentra en la posición 0. Cada nodo 6ene el valor del elemento que porta y dos índices que indican las posiciones dentro del array donde están los nodos hijos Niveles = 4 Capacidad máxima y longitud Ahora la capacidad se expresa en número de nodos y el árbol no tiene porqué estas equilibrado 8 9 6 7 4 5 2 3 0 1 Índice izquierdo 7 1 6 1 - - 0 6 3 Índice derecho elemento
  • 192.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 12 Algoritmos sobre árboles binarios Algoritmos sobre árboles binarios Como viene siendo frecuente a lo largo de este curso, los tres 6pos de algoritmos canónicos aplicables a cualquier estructura de datos son recorrido, búsqueda y ordenación. En este caso, la ordenación debe entenderse como una reorganización de los nodos del árbol para favorecer algún criterio (`picamente la búsqueda). Sin embargo, no estudiaremos ningún algoritmo de ordenación y nos centraremos sólo en recorridos y búsquedas Algoritmos sobre árboles binarios I. Recorrido El recorrido de los elementos de un árbol binario devuelve un iterador que permite acceder secuencialmente a los mismos según aparecen almacenados en la estructura. Sin embargo, existen distintos criterios de secuenciamiento que pueden aplicarse para construir un recorrido. Aquí estudiaremos los 5 más típicamente aplicados II. Búsqueda La búsqueda de un elemento sobre los nodos de un árbol binario se realiza de forma recursiva dada la definición del tipo lo que imprime un coste lineal al algoritmo en el peor caso. La ventaja de este tipo de algoritmos, con respecto a sus equivalentes en otras estructuras de datos es que el proceso no es destructivo con lo que no se requiere utilizar un iterador (con copia) ni reconstruir la estructura tras la aplicación del algoritmo Independenciadela implementación
  • 193.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 13 Algoritmos sobre árboles binarios Recorrido de los elementos de un árbol binario Los recorridos que pueden aplicarse sobre las estructuras arborescentes son varios en función de la estrategia de secuenciamiento que se aplique sobre los elementos del 6po abstracto de datos. En concreto es posible dis6nguir 5 estrategias organizados de la siguiente manera Recorridos sobreárboles I. Recorridos en profundidad Se recorre el árbol recursivamente en profundidad. En función de donde se aloje, relativamente cada nodo con respecto a sus hijos izquierdos y derechos se distinguen 3 recorridos en profundidad II. Recorridos en anchura Preorden Inorden Postorden Cada nodo se inserta antes de sus hijos izquierdos y derechos Cada nodo se inserta entre sus hijos izquierdos y derechos Cada nodo se inserta detrás de sus hijos izquierdos y derechos S A C O C A S O c A O S Se recorre el árbol en anchura colocando primero todos los elementos del nivel k antes de pasar a colocar los del nivel k + 1. En función del orden en que se disponen los elementos por niveles se distinguen dos recorridos en anchura Anchura Anchura inversa Se disponen los elementos del árbol por niveles de izquierda a derecha y desde la raíz a las hojas Se disponen los elementos de forma inversa a como establece un recorrido en anchura O C A S S A C O
  • 194.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 14 Algoritmos sobre árboles binarios Recorrido de los elementos de una árbol binario Para implementar el iterador de los árboles binarios u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola class BTreeIterator<T> implements IteratorIF<T> { private IteratorIF<T> iterator; /** * Constructor para QueueIterator. * @param handler el manejador de arboles binarios. * @param type el tipo de recorrido. */ public BTreeIterator (BTreeIF<T> handler, int type) { QueueIF<T> traverse = null; switch (type) { case BTreeIF.PREORDER: traverse = preorder (handler); break; case BTreeIF.INORDER: traverse = inorder (handler); break; case BTreeIF.POSTORDER: traverse = postorder (handler); break; case BTreeIF.LRBREADTH: traverse = lrBreadth (handler); break; case BTreeIF.RLBREADTH: traverse = rlBreadth (handler); break; } this.iterator = new QueueIterator<T> (traverse); } /** * Devuelve el siguiente elemento de la iteracion. * @return el siguiente elemento de la iteracion. */ @Override public T getNext () { return iterator.getNext (); } La iteración de los elementos del árbol se delega en el iterador de cola que es construido en el constructor. La función de reset está garantizada Iteración con reset La función de avance delega en el iterador de cola que se ha construido previamente. Esta aproximación simplifica las operaciones pero penaliza el tiempo de la construcción del iterador Avance Construcción En función del valor del parámetro del tipo de recorrido, el constructor invoca a una u otra función privada que devuelve una cola con los elementos dispuestos en el orden apropiado. Después se construye un iterador sobre la cola resultante
  • 195.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 15 Algoritmos sobre árboles binarios Recorrido de los elementos de una árbol binario Para implementar el iterador de los árboles binarios u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola /** * Devuelve cierto si existen mas elementos en el iterador. * @return cierto si existen mas elementos en el iterador. */ @Override public boolean hasNext () { return iterator.hasNext (); } /** * Restablece el iterador para volver a recorrer la estructura. */ @Override public void reset () { iterator.reset (); } private QueueIF<T> preorder (BTreeIF<T> tree) { QueueIF<T> traverse = new QueueDynamic<T> (); if (tree == null) return traverse; T element = tree.getRoot (); BTreeIF<T> lTree = tree.getLeftChild (); BTreeIF<T> rTree = tree.getRightChild (); QueueIF<T> lTraverse = preorder (lTree); QueueIF<T> rTraverse = preorder (rTree); traverse.add (element); addAll (traverse, lTraverse); addAll (traverse, rTraverse); return traverse; } La función de siguiente se delega sobre el iterador de cola. Habrá siguientes elementos que visitar si el iterador de cola aún no ha finalizado Siguiente El recorrido en preorden inserta primero en la cola cada nodo y luego construye recursivamente las colas de los subárboles izquierdo y derecho. Mediante el método allAll dichas colas se añaden, en ese orden a la cola principal. Preorden Reset La función de restablecimiento del iterador se delega igualmente sobre el método homónimo del iterador de colas
  • 196.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 16 Algoritmos sobre árboles binarios Recorrido de los elementos de una árbol binario Para implementar el iterador de los árboles binarios u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola private QueueIF<T> inorder (BTreeIF<T> tree) { QueueIF<T> traverse = new QueueDynamic<T> (); if (tree == null) return traverse; T element = tree.getRoot (); BTreeIF<T> lTree = tree.getLeftChild (); BTreeIF<T> rTree = tree.getRightChild (); QueueIF<T> lTraverse = inorder (lTree); QueueIF<T> rTraverse = inorder (rTree); addAll (traverse, lTraverse); traverse.add (element); addAll (traverse, rTraverse); return traverse; } private QueueIF<T> postorder (BTreeIF<T> tree) { QueueIF<T> traverse = new QueueDynamic<T> (); if (tree == null) return traverse; T element = tree.getRoot (); BTreeIF<T> lTree = tree.getLeftChild (); BTreeIF<T> rTree = tree.getRightChild (); QueueIF<T> lTraverse = postorder (lTree); QueueIF<T> rTraverse = postorder (rTree); addAll (traverse, lTraverse); addAll (traverse, rTraverse); traverse.add (element); return traverse; } private void addAll (QueueIF<T> q, QueueIF<T> p) { while (!p.isEmpty ()) { T element = p.getFirst (); q.add (element); p.remove (); } } El recorrido en inorden inserta primero en la cola, los elementos del subárbol izquierdo, luego el nodo en curso y finalmente los elementos del subárbol derecho. Inorden El recorrido en postorden inserta primero los elementos de los subárboles izquierdo y derecho y después anexa el nodo en curso. Postorden La función addAll inserta en una cola todos los elementos de una segunda cola Encolar todos
  • 197.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 17 Algoritmos sobre árboles binarios Recorrido de los elementos de una árbol binario Para implementar el iterador de los árboles binarios u6lizaremos una cola donde se almacenarán en la construcción los elementos dispuestos adecuadamente según el 6po de recorrido seleccionado. La iteración entonces se delegará en el iterador de esa cola private QueueIF<T> lrBreadth (BTreeIF<T> tree) { QueueIF<T> traverse = new QueueDynamic<T> (); QueueIF<BTreeIF<T>> aux = new QueueDynamic<BTreeIF<T>> (); aux.add (tree); while (!aux.isEmpty ()) { BTreeIF<T> aTree = aux.getFirst (); T element = tree.getRoot (); BTreeIF<T> lTree = aTree.getLeftChild (); BTreeIF<T> rTree = aTree.getRightChild (); if (lTree != null) aux.add (lTree); if (rTree != null) aux.add (rTree); traverse.add (element); aux.remove (); } return traverse; } private QueueIF<T> rlBreadth (BTreeIF<T> tree) { QueueIF<T> traverse = lrBreadth (tree); StackIF<T> aux = new StackDynamic<T> (); while (!traverse.isEmpty ()) { T element = traverse.getFirst (); aux.push (element); traverse.remove (); } while (!aux.isEmpty ()) { T element = aux.getTop (); traverse.add (element); aux.pop (); } return traverse; } El recorrido en anchura utiliza dos colas para su construcción. En una se van insertando los elementos resultantes del recorrido. La otra es una cola auxiliar que sirve para almacenar los subárboles pendientes de ser procesados en cada paso Anchura La anchura inversa es el recorrido inverso al anterior por tanto la implementación más sencilla consiste en generar un recorrido en anchura e invertirlo posteriormente. Para ello se utiliza una pila. Primero se mueven los elementos de la cola resultante a una pila. Después se extraen de la cola para insertarlos en una pilla. Finalmente se extraen de la pila para insertarlos nuevamente en la cola Anchura inversa
  • 198.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 18 Algoritmos sobre árboles binarios Búsqueda de un elemento sobre un árbol binario La búsqueda de un dato sobre los elementos contenidos en un árbol binario es un problema de recorrido que termina cuando se encuentra el elemento buscado dentro de la estructura de datos. Dado que se trata de un 6po con definición recursiva es posible aplicar dos 6pos de algoritmos. La búsqueda aplica una estrategia recursiva para recorrer en profundidad el árbol. Alterna6vamente también se puede encontrar una solución itera6va basada en búsqueda con cen6nela u6lizando alguno de los recorridos secuenciales que acabamos de describir. Búsqueda binaria @Override public boolean contains (T element) { if (element == null) return false; return element.equals (getRoot ()) || (getLeftChild () != null) ? getLeftChild ().contains (element) : false || (getRightChild () != null) ? getRightChild ().contains (element) : false; } Es esta implementación se realiza una búsqueda con recursiva sobre la estructura de nodos del árbol. El recorrido corresponde a un preorden Búsqueda con cen8nela @Override public boolean contains (T element) { boolean found = false; Iterator<T> it = getIterator (this, BTreeIF.INORDER); while (!found && it.hasNext ()) { T anElement = it.getNext (); found = anElement.equals (element); } return found; } En la búsqueda con cen6nela la solución itera sobre los elementos de la estructura obtenidos a par6r de un iterador de cualquier 6po de recorrido (por ejemplo inorden)
  • 199.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 19 Algoritmos sobre árboles binarios Árboles binarios de búsqueda Los árboles binarios de búsqueda son u6lizados para disponer los elementos de un conjunto de tal forma que se op6mice la localización de los mismos alcanzándose un coste temporal logarítmico con respecto al volumen de datos medido para el peor caso. La disposición de los elementos debe seguir, naturalmente, ciertos criterios de orden Un árbol binario es de búsqueda si es vacio o la raíz es mayor que el máximo elemento del subárbol izquierdo y menor que el mínimo elemento del subárbol derecho y, a su vez, ambos subárboles son árboles binarios de búsqueda 8 3 1 6 4 7 10 14 13 En efecto, este es un árbol binario de búsqueda puesto que verifica que todos los elementos en el subárbol izquierdo de cada nodo son menores que dicho nodo y los que se encuentran en el subárbol derecho mayores que el mismo }
  • 200.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 20 Algoritmos sobre árboles binarios Árboles binarios de búsqueda Un árbol de búsqueda es equilibrado si la altura de los subárboles izquierdo y derecho es exactamente la misma Árboles equilibrados Para garan6zar realmente un coste logarítmico en la búsqueda es necesario asegurarse de que la estructura se man6ene equilibrada. Es decir, que la proporción de nodos a la izquierda y derecha de cualquier nodo sea la misma 4 2 6 5 71 3 5 4 3 2 6 7 1 En una estructura jerárquica equilibrada el coste de la búsqueda es O (log n) } Si el árbol binario de búsqueda no está equilibrado, en el caso peor se puede llegar a c o n v e r A r e n u n a estructura lineal con coste O(n) } Los árboles binarios de búsqueda son u6lizados para disponer los elementos de un conjunto de tal forma que se op6mice la localización de los mismos alcanzándose un coste temporal logarítmico con respecto al volumen de datos medido para el peor caso. La disposición de los elementos debe seguir, naturalmente, ciertos criterios de orden
  • 201.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 21 Algoritmos sobre árboles binarios Árboles binarios de búsqueda Estrategias de equilibrado y rotaciones Los árboles binarios de búsqueda son u6lizados para disponer los elementos de un conjunto de tal forma que se op6mice la localización de los mismos alcanzándose un coste temporal logarítmico con respecto al volumen de datos medido para el peor caso. La disposición de los elementos debe seguir, naturalmente, ciertos criterios de orden Dado que la estructuración jerárquica de los árboles de búsqueda no responde a un requisito del problema sino a una disposición conveniente de los datos es posible cambiar la misma según se hacen inserciones o extracciones para mantener el equilibrio. Las rotaciones se encargan de ello (véase hap://qma6ca.com) Rotación simple a derechas Rotación simple a izquierdas 8 4 62 10 n n n+1 4 8 106 2 n nn+1 n n n+1 n n n+1 4 3 8 96 8 4 63 9
  • 202.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 22 Algoritmos sobre árboles binarios Árboles binarios de búsqueda Estrategias de equilibrado y rotaciones Los árboles binarios de búsqueda son u6lizados para disponer los elementos de un conjunto de tal forma que se op6mice la localización de los mismos alcanzándose un coste temporal logarítmico con respecto al volumen de datos medido para el peor caso. La disposición de los elementos debe seguir, naturalmente, ciertos criterios de orden Dado que la estructuración jerárquica de los árboles de búsqueda no responde a un requisito del problema sino a una disposición conveniente de los datos es posible cambiar la misma según se hacen inserciones o extracciones para mantener el equilibrio. Las rotaciones se encargan de ello (véase hap://qma6ca.com) Rotación doble a derechas Rotación doble a izquierdas n+1 n+1 n n+1 9 105 1 7 86 7 5 9 1 6 8 10 n+1 n+1 n n+1 3 5 9 7 6 8 10 n+1 n+1 n+1n 7 5 3 n+1 6 n 9 8 10 n+1 n+1
  • 203.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 23 Algoritmos sobre árboles binarios Árboles binarios de búsqueda Tipos de árboles de búsqueda Los árboles binarios de búsqueda son u6lizados para disponer los elementos de un conjunto de tal forma que se op6mice la localización de los mismos alcanzándose un coste temporal logarítmico con respecto al volumen de datos medido para el peor caso. La disposición de los elementos debe seguir, naturalmente, ciertos criterios de orden Dado que la restricción acerca del equilibrio es demasiado fuerte, se han ideado algunos 6pos de árboles de búsqueda cuasi-equilibrados que aplican las rotaciones anteriores como eje fundamental del mantenimiento logarítmico de las operaciones de localización Árboles AVL Árboles roji – negros En los árboles AVT las alturas de los hijos izquierdo y derecho de cada subárbol sólo pueden diferir, a lo sumo en una unidad aplicándose rotaciones para el reequilibrado. Inserción y borrado son logarítmicas. La primera debido a un coste constante de la rotación. La segunda porque la propagación solo se exAende hasta la raíz Para el resto de operaciones, el coste temporal, tanto promedio como en el caso peor, es también logarítmico aunque su coste espacial resulta lineal. [Weiss, 484-492] [Drozdek, 255-260] Los árboles roji-negros son estructuras auto-equilibradas en la que los nodos Aenen un atributo adicional, su color (rojo o negro). La raíz es siempre negra. Los dos hijos de un nodo rojo deben ser negros. Todas las hojas son negras. Y todos los caminos desde un nodo antecesor hasta cualquiera de sus hojas deben contener el mismo número de nodos negros. Se uAlizan rotaciones para reequilibrar. Se pueden eliminar el segundo recorrido de los AVL mediante una transformación descendente de algunos de los nodos (cambio de color, inserción de una hoja y rotación). Sin embargo, el borrado Aene una codificación compleja. Su coste temporal es logarítmico. [Weiss, 492-505]
  • 204.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 24 Algoritmos sobre árboles binarios Árboles binarios de búsqueda Tipos de árboles de búsqueda Los árboles binarios de búsqueda son u6lizados para disponer los elementos de un conjunto de tal forma que se op6mice la localización de los mismos alcanzándose un coste temporal logarítmico con respecto al volumen de datos medido para el peor caso. La disposición de los elementos debe seguir, naturalmente, ciertos criterios de orden Dado que la restricción acerca del equilibrio es demasiado fuerte, se han ideado algunos 6pos de árboles de búsqueda cuasi-equilibrados que aplican las rotaciones anteriores como eje fundamental del mantenimiento logarítmico de las operaciones de localización Árboles AA Árboles B Los árboles AA son una variante de los roji-negros cuyo atributo adicional es el nivel en lugar del color. El nivel representa el número de enlaces a hijos izquierdos en el camino hacia la hoja (para las hojas 1). Un padre rojo y su hijo se conectan por un enlace horizontal y Aenen el mismo nivel. El nivel del hijo de un padre negro será una unidad menos que el de su padre . La inserción siempre se realiza en el nivel más bajo del árbol. Se uAlizan rotaciones simples para reequilibrar si es preciso. El borrado se limita a la eliminación de un nodo de nivel 1. Su coste espacial y temporal es igual al de los rojinegros aunque los árboles AA se suelen aplanar algo más. [Weiss, 505-512] Los árboles B son una generalización de los árboles binarios de búsqueda en los que un nodo interno puede tener más de dos hijos hasta un cierto límite. OpAmizan la lectura de grandes bloques de datos. Un árbol B de orden k es un árbol k-ario en que los datos se almacenan en las hojas. Un nodo interno contendrá k-1 claves de búsqueda, donde la j-ésima clave será la menor del árbol j+1-ésimo. La raíz bien será una hoja bien tendrá un rango de hijos entre 2 y k. Los nodos internos Aenen entre k/2 y k hijos. La profundidad de todas las hojas es la misma y Aenen entre h/2 y h hijos, donde h es un valor constante y prefijado. Al maximizar el número de hijos la altura decrece reduciéndose el coste de acceso (logaritmo en base k) y los reequilibrios. [Weiss, 512-519]
  • 205.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 25 Problemas y ejercicios Ejercicios Pueden encontrarse mul6tud de situaciones donde es necesario manipular la estructura interna de los elementos de un árbol binario. A con6nuación presentamos algunos ejercicios que vienen a ejemplificar tales situaciones Diseñe una función devuelva el número de elementos que con6ene un árbol binario I. Contar elementos Diseñe una función que devuelve la suma de todos los elementos de un árbol binario de enteros II. Sumar elementos Diseñe una función recursiva que devuelva una lista con todos los elementos pares de un árbol de enteros III. Encontrar pares Diseñe una función recursiva que dado un árbol binario de enteros devuelva otro árbol solamente con los elementos pares IV. Eliminar impares Diseñe una función que reorganice los elementos de un árbol para conver6rlo en árbol binario de búsqueda V. Equilibrar Diseñe una función recursiva que determine si dos árboles binarios son estructuralmente idén6cos VI. Comparación de árboles Diseñe una función recursiva que indique si dos árboles binarios son la imagen especular el uno del otro VII. Imagen especular Diseñe una función que dado un árbol binario de enteros sus6tuya el valor en cada nodo por el valor acumulado de todos los nodos anteriores a él en un recorrido en profundidad VIII. Sumar anteriores Diseñe una función que determine si un árbol binario es un árbol binario de búsqueda IX. Es árbol de búsqueda
  • 206.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 26 Problemas y ejercicios Problemas Las árboles binarios son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de este 6po abstracto de datos. La forma en que los compiladores manejan las expresiones aritmé6co-lógicas es mediante el uso de un árbol sintác6co donde los nodos hoja corresponden a operandos y los intermedios a operaciones. ¿Sabría idear un algoritmo que calcule el valor de la siguiente expresión aritmé6ca expresada en forma de un árbol binario? Árboles sintácticos de operadores Juegos y representación de escenarios 3D En los motores de renderizado 3D (ampliamente u6lizados en el desarrollo de juegos en subje6vo) la representación de los escenarios tridimensionales u6liza árboles binarios para descomponer las texturas poligonales en formas progresivamente más sencillas.
  • 207.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 27 Problemas y ejercicios Problemas Como aplicación especifica de los árboles de búsqueda binarios aparecen los diccionarios. Un diccionario es una estructura jerárquica sobre la cual se disponen los términos en las hojas mientras que los nos intermedios son prefijos organizados lexicográficamente Diccionarios Codificación Huffman La codificación Huffman es una técnica de compresión de datos que asigna representaciones de longitud variable a cada dato en función se su probabilidad de aparición (mayor probabilidad, menor longitud). La tabla de correspondencias suele representarse en forma de árbol binario (0 izquierda, 1 derecha) para representar la cadena de 0s y 1s que representa cada dato Las árboles binarios son un 6po abstracto de datos que se u6liza recurrentemente en los problemas de cierta complejidad de programación. A con6nuación planteamos algunos ejemplos de problemas que se resuelven con el uso de este 6po abstracto de datos.
  • 208.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 28 Bibliograia BibliograSa Bibliografía básica Estructuras de datos en java. Weiss, Mark Allen. Pearson Addison – Wesley. ISBN 9788478290352
  • 209.
    Tipos abstractos de datos jerárquicos. Árboles binarios Javier Vélez Reyesjvelez@lsi.uned.es8 - 29 Bibliograia BibliograSa Bibliografía complementaria Estructura de datos y algoritmos en java. A. Drozdek. Thomsom. ISBN: 9706866116. 2007 Estructuras de datos con Java. J. Lewis, J. Chase. Pearson – Addison Wesley. ISBN 13: 9788420541914