Logo Studenta

URJC _Universidad Rey Juan Carlos_ _ Ingeniería Informática _ Apuntes_practicas y exámenes de pascal _ Estructura

Esta es una vista previa del archivo. Inicie sesión para ver el archivo original

Estructura de Datos/Practicas y ejercicios/EjercicioConcesionarios_Soto_Junio2013_ED_Vicalvaro.pdf
 Estructuras de Datos 
14 de Junio de 2013 
Ejercicio 
La asociación de vendedores de coches en España quiere tener automatizado todo el proceso 
de acceso a la información relacionada con la venta de coches por toda la geografía española. 
Para ello deben tener registrada toda la información de los diferentes concesionarios de venta 
de coches en todo el país. 
Algunos concesionarios sólo venden coches de una marca, mientras que otros pueden vender 
coches de varias marcas. Cada concesionario tendrá una dirección postal diferente, y pueden 
tener más o menos coches en venta, pudiendo variar la cantidad de coches que venden 
constantemente y, en el caso de concesionarios que venden más de una marca, también 
pueden aumentar o eliminar las marcas que venden. 
A su vez, pueden surgir nuevos concesionarios de venta en aquellas zonas donde el mercado 
lo demande, o cerrar algunos concesionarios si no son rentables. 
Se proporciona la siguiente interfaz para el TAD TCoche. Además se muestra cómo la marca 
de los coches se identificará en la aplicación mediante un código numérico entero. 
 
 
 
 
 
 
 
 
Se pide: 
a) Definir los tipos TConcesionario y TRedConcesionarios. Explicar de forma 
razonada la definición de tipos que se haga en cada caso. Se pretende que el acceso 
a la información de los concesionarios, así como la modificación de esta 
información sea lo más eficiente posible. 
b) Implementar una operación para añadir un nuevo concesionario a la red de 
concesionarios. Se indicará cuál es su dirección postal, además del listado de marcas 
(o una única marca) de coches que podrá vender. Se valorará positivamente la 
eficiencia a la hora de hacer esta operación. 
c) Implementar una operación que permita añadir un nuevo coche para vender en un 
concesionario determinado. Se indicará por lo tanto la dirección postal del 
concesionario donde se añadirá un nuevo coche, la marca del coche y el propio 
coche a vender. 
c) Implementar una operación para eliminar la venta de coches de una determinada 
marca de un concesionario determinado. Para ello se proporciona la dirección del 
concesionario y la marca cuyos coches se dejan de vender en el concesionario. En 
caso de quedarse sin ninguna marca, el concesionario se cerrará. 
 
Nota: Todas las operaciones nuevas que vayan surgiendo, tanto del TAD TCoche, como de 
los TADs TConcesionario y TRedConcesionarios, deberán implementarse, asegurando que 
cada operación es implementada en el TAD que le corresponde. 
INTERFACE 
TYPE 
TCoche = RECORD 
 modelo: string; 
 color: string; 
END; 
PROCEDURE Inicializar (VAR c:TCoche; mod, col: STRING); 
PROCEDURE InicializarTeclado(VAR c: TCoche); 
PROCEDURE Imprimir(c: TCoche); 
… 
 
IMPLEMENTATION … END. 
CÓDIGOS DE LAS 
MARCAS DE COCHES: 
1 -> Toyota 
2 -> Renault 
3 -> Mercedes 
4 -> Audi 
5 -> Mazda 
6 -> Opel 
7 -> Kia 
… 
Estructura de Datos/Practicas y ejercicios/ejercicio_prueba_escrita_mayo2014_GII_vicalvaro.pdf
 
Estructuras de Datos 
 Mayo de 2014 
 
1) (Prueba escrita práctica, 4 puntos) El mundial de fútbol se acerca. Se desea modelar el 
campeonato a través de la estructuración de las diferentes selecciones. Ya se conoce que 
los grupos A-H serán los siguientes: 
Grupo A: Brasil, Croacia, Camerún, México. 
Grupo B. España, Chile, Australia, Holanda. 
Grupo C. Colombia, Costa de Marfil, Japón, Grecia. 
Grupo D. Uruguay, Italia, Costa Rica, Inglaterra. 
Grupo E. Suiza, Ecuador, Honduras, Francia. 
Grupo F. Argentina, Nigeria, Irán, Bosnia – Herzegovina. 
Grupo G. Alemania, Ghana, Estados Unidos, Portugal. 
Grupo H. Bélgica, Algeria, Corea del Sur, Rusia. 
Además, supongamos que cada selección puede llevar un máximo de 23 jugadores (mínimo 
15), 3 técnicos (mínimo 1) y 2 médicos (no hay mínimo), pero cada comité nacional decide 
cómo llenarlo (dentro de los mínimos y máximos, por ejemplo 15, 1, 0 de cada tipo, 20, 2, 1, o 
cualquier otra combinación válida). 
a) (0.5 puntos) Escriba el código en Pascal para definir una estructura eficiente que pueda 
contener toda la información de los 8 Grupos, de manera que se tenga acceso en O(1) a cada 
grupo mediante su identificador de Grupo (char) y acceso a cada selección dentro del grupo 
en O(n) mediante el nombre de la selección (de tipo TCountryTeam definido en otra unidad 
independiente y básicamente de tipo string). Dentro de la selección se podrá iterar por la 
lista de convocados de forma lineal. Para desglosar los miembros convocados entre jugadores, 
técnicos y médicos se utilizará un tipo TMemberType con una codificación que indicará ‘P’= 
player (jugador), . ‘T’= tech (técnico), ‘D’= doctor (médico), para cada miembro del equipo. La 
información personal de cada miembro vendrá dada por un tipo TMember definido en otra 
unidad (habrá que dejar disponible pero no hará falta crear). 
b) (1 punto) Escriba el código en Pascal de los subprogramas necesarios para insertar en la 
estructura anterior los equipos en sus correspondientes grupos. Como no se conocen qué 
miembros seleccionados irán en cada equipo, bastará con introducir los nombres de los 
equipos y dejar su estructura de equipo vacía. 
c) (1.5 punto) Escriba el código en Pascal de los subprogramas necesarios para insertar en cada 
equipo la información de sus miembros teniendo en cuenta que se deja disponible un 
subprograma con prototipo: 
PROCEDURE ReadMemberFromDisk(country: TCountryTeam; VAR member: 
TMember; VAR type:TMemberType; VAR error: Boolean) que cada vez que se le 
invoca con el identificador de una selección (TCountryTeam) devuelve, o bien la información 
personal del miembro, su tipo (‘P’, ‘T’, ‘D’) y error a FALSE, o directamente basura y error a 
TRUE si no hay más información que cargar para esa determinada selección. 
d) (1 punto) Se dispone de una función que devuelve el número de goles que ha marcado un 
miembro TMember de tipo ‘P’ (jugador, “player “como TMemberType) que se le pasa. 
Supongamos su prototipo: 
FUNCTION GetGoalsNumber(player: TMember): integer; 
Se pide crear el listado de selecciones (de tipos TCountryTeam) más goleadoras (de mayor a 
menor). Los goles de cada selección se calcularán mediante la suma de goles de todos sus 
jugadores. 
Estructura de Datos/Practicas y ejercicios/ExamenMayo2015_GII_vicalvaro.pdf
 
Estructuras de Datos 
 Mayo de 2015 
 
APELLIDOS: __GII __GII+ADE NOMBRE: 
TITULACIÓN: DNI: 
Duración: 1:45 h. 
Calificación: 
 Se recuerda que, según la guía docente, el 15% de la nota final se corresponde con pruebas 
prácticas realizadas, 25% con prueba escrita teórica y 60% con prueba escrita práctica. Se 
sugiere dejar 1 hora de esfuerzo en la resolución del ejercicio 5. Contestar en la hoja de 
enunciados los 4 primeros ejercicios. 
 
1) (Prueba escrita teoría, 0.5 puntos) Resuma brevemente las características más importantes 
de un grafo ponderado y dirigido en representación estática frente a su representación 
dinámica. A continuación defina un tipo Grafo en representación de listas de adyacencia 
con un TElemento genérico definido en otra unidad. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2) (Prueba escrita teoría, 1 punto) Calcule, mediante el método de expansión de recurrencias 
visto en clase, la complejidad algorítmica en notación O() del algoritmo del Búsqueda 
binaria o dicotómica en el que se busca un elemento en una lista de valores ordenados. 
Además, si se dispone de un array de 4096 valores, ¿cuántas llamadas recursivas se deben 
realizar para llegar al caso base? Justifique matemáticamente su respuesta. 
 
 
 
 
 
 
 
 
 
 
 
 
 
3) (Prueba escrita teoría, 1 punto) Especificar algebraicamente, tal y como se ha visto en clase, 
la sintaxis y la semántica de las operaciones Espejo y Postorden de árboles binarios.
Utilice 
las operaciones de la especificación de árboles binarios vista en clase que necesite. 
 
 
 
 
 
 
 
4) (Prueba escrita práctica, 2 puntos) Defina el tipo de dato para crear una estructura 
dinámica doblemente enlazada tipo FIFO (first input, first output) cuyo orden de 
complejidad en inserción y extracción sea de O(1). El tipo elemento que guarde puede ser 
de tipo TElemento genérico (que estaría definido en otra unidad). A continuación, realizar 
los procedimientos de Insertar y Eliminar. 
 
 
 
 
 
 
 
 
 
 
 
 
 
5) (Prueba escrita práctica, 4 puntos) ELECCIONES 
Como estamos en temporada de elecciones se desea modelar un novedoso problema de 
sistemas electorales. 
 
En el país de Nunca Jamas, los ciudadanos pueden distribuir su voto entre varios candidatos, 
reflejando así sus preferencias con gran precisión, tal como expresa su lema “Una persona, 
cien votos”, característico de aquel pequeño país. Además, pueden emitirse fantásticos votos 
de castigo (negativos). 
 
Para votar, los Nuncajamasienses rellenan una papeleta en la que reparten un máximo de 100 
puntos (positivos o negativos, cuenta en valor absoluto) entre los partidos políticos que se 
presentan a los comicios. La validez de una papeleta consiste en que la suma de los valores 
absolutos de los puntos asignados a los candidatos no supere los 100 puntos. 
 
Desgraciadamente el número de partidos políticos es desconocido hasta el día de la votación, 
aunque los aspirantes a presidentes son viejos conocidos de todos y definen el nombre de su 
partido, tales como los famosos partidos MarianoGarzón, PabloSanchez, PedroIglesias, 
AlbertRajoy, AlbertoDiez, RosaRivera, y otros muchos que a veces se presentan. 
 
Por si fuera poco, y para la desgracia de los Nuncajamasienses, las papeletas que depositan en 
las urnas tienen un campo de DNI y edad del votante, que sirven para invalidar votos repetidos 
o de menores de 25 años (y posiblemente para aplicarles algún tipo de castigo), y espacio para 
apuntar los votos que se asignan a cada partido (dado que no se sabe cuántos partidos se 
presentan pero todos tienen que recibir puntos, ya sean negativos, cero o positivos). Para 
controlar el peligro de votos repetidos hay un censo con la información de todos los 
ciudadanos. 
 
Para el recuento de votos, si bien todos cuentan, no lo hacen por igual, sino que lo hacen 
proporcionalmente a la edad del votante. Cada voto va pesado por un factor 0,01*edad (de 
manera que un voto de ciudadano de 30 años cuenta 0,3 mientras que de uno de 100 cuenta 
1,0 puntos). 
 
El mecanismo electoral pone a cero una tabla de marcadores con el nombre del partido y los 
votos que va obteniendo al objeto de contar los puntos de cada candidato. Se pide: 
 
a) [0.5 punto] Definir en PASCAL los tipos de datos para la papeleta, la tabla de marcadores 
con nombre de partido y puntuación entera para el recuento final, y una estructura para el 
censo electoral, que registre el DNI de cada votante, su edad, un campo para conocer si ha 
votado o no, y los puntos que ha asignado a cada candidato electoral. Esta última 
estructura fue creada por los Servicios Inteligentes de Nunca Jamás como estructura de 
búsqueda en la que, en casos habituales, suele ser más rápida que el listado (aunque no se 
garantice). Hacer también el subprograma para inicializar una tabla de marcadores a cero y 
un subprograma que, dada una papeleta, la valide o invalide (devolviendo un valor 
booleano). 
 
 
b) [1 puntos] Escribir los tipos de datos y los subprogramas necesarios para que se registre en 
la estructura del censo electoral el voto válido de un ciudadano. Inicialmente el censo 
tiene los datos de sus ciudadanos (DNI, nombre, edad y el campo de haber votado a falso) 
salvo la puntuación que asigna a los partidos. Todos los votos que se registran se suponen 
válidos. Para registrar el voto en el censo se busca al ciudadano por DNI y, si no ha votado 
antes y es una papeleta válida, se inserta la información de su papeleta (nadie sabe lo que 
le pasa a un ciudadano que vota por duplicado o incorrectamente, pero nada bueno, su 
campo de voto queda a falso para siempre). 
 
 
c) [1.5 punto] Escribir los subprogramas necesarios para que, dada una tabla de marcadores 
y la estructura de censo electoral, añada los puntos consignados en el censo de todos los 
ciudadanos que han votado a la tabla de marcadores. Como se sabe, los puntos que 
corresponden a un candidato se calculan multiplicando los puntos que tiene asignados en 
la papeleta multiplicados por la edad del votante con su factor de corrección. 
 
 
d) [1 punto] Tradicionalmente, el candidato ganador quiere conocer la identidad de sus 
ciudadanos más devotos para colocarlos en los puestos más destacados de su gobierno. 
Para ello, los Servicios Secretos utilizan el censo para la identificación de los 10 votantes 
que más puntos han aportado (teniendo en cuenta su edad) a la elección del ganador. 
Define tipos de datos, si fuera necesario, y escribe un subprograma que devuelva la 
estructura que guarde los 10 votantes que más han colaborado al triunfo del ganador 
junto con la puntuación, ordenados de mayor a menor aportación. 
Estructura de Datos/Practicas y ejercicios/hojaProblemasComplejidad.pdf
 1 
Universidad Rey Juan Carlos 
1º GII/GII+ADE (Vicálvaro) 
 
Asignatura: Estructuras de Datos 
 
HOJA DE PROBLEMAS Nº 1: Complejidad de Algoritmos 
____________________________________________________________ 
 
Estudio de la complejidad (tiempo de ejecución en el peor caso) de algoritmos. 
 
1) Calcular la complejidad de los siguientes trozos de algoritmos en función de n. 
 
a) x := 0; 
PARA i DESDE 1 HASTA n HACER 
 PARA j DESDE 1 HASTA n HACER 
PARA k DESDE 1 HASTA n HACER 
 x := x + 1; 
 
b) x := 0; 
SI (n MOD 2 /= 0) ENTONCES 
 PARA i DESDE 1 HASTA n HACER 
 PARA j DESDE 1 HASTA i HACER 
 x := x + 1; 
SI NO 
 X := -1; 
 
c) x := 0; 
PARA i DESDE 1 HASTA n HACER 
 PARA j DESDE 1 HASTA n
2
 HACER 
 PARA k DESDE 1 HASTA n
3
 HACER 
 x := x + 1; 
 
d) x := 0; 
PARA i DESDE 1 HASTA n HACER 
 PARA j DESDE 1 HASTA i HACER 
 PARA k DESDE j HASTA n HACER 
 x := x + 1; 
 
2) Algoritmo iterativo para hallar el máximo de un vector v con n elementos. 
 
máximo := v(1); 
PARA i DESDE 2 HASTA n HACER 
 SI v(i)>máximo ENTONCES máximo := v(i) 
 
3) Algoritmo para ordenar de menor a mayor un vector v con n elementos (ordenación por selección). 
(se supondrá que la operación Intercambiar tiene un tiempo de ejecución constante). 
 
PARA i DESDE 1 HASTA n-1 HACER 
 pmin := i; 
 PARA j DESDE i+1 HASTA n HACER 
 SI v(j) < v(pmin) ENTONCES pmin := j; 
 Intercambiar(v(i), v(pmin)); 
 2 
4) Algoritmo para ordenar de menor a mayor un vector v con n elementos (ordenación por el método de 
inserción). 
 
PARA i DESDE 2 HASTA n HACER 
 pos := i; 
 x := v(i); 
 seguir := CIERTO; 
 MIENTRAS pos>1 y seguir HACER 
 SI x < v(pos-1) ENTONCES 
v(pos) := v(pos-1) 
SI NO seguir:= FALSO; 
 pos := pos – 1; 
 v(pos):= x; 
 
5) Algoritmo para ordenar de menor a mayor un vector v con n elementos (ordenación por el método de 
la burbuja). (se supondrá que la operación Intercambiar tiene un tiempo de ejecución constante). 
 
paso := 1; 
intercambio := CIERTO; 
MIENTRAS (paso <= n-1) Y intercambio HACER 
 intercambio := FALSO; 
 PARA i DESDE 1 HASTA n-paso HACER 
 SI v(i) > v(i+1) ENTONCES 
 Intercambiar(v(i),v(i+1)); 
 Intercambio := CIERTO; 
 paso := paso + 1; 
 
6) Algoritmo para buscar secuencialmente un elemento en un vector v con n elementos. 
 
FUNCIÓN Buscar (v:TipoVecor; buscado:TipoElemento) DEVUELVE Booleano 
i := 1; 
MIENTRAS (i<=n) Y (v(i)/=buscado) HACER 
 i := i + 1; 
 DEVOLVER i<=n; 
 
7) Algoritmo iterativo para buscar un elemento en un vector ordenado v con n elementos mediante 
búsqueda binaria. 
 
FUNCIÓN Pertenece(v:TipoVector;buscado:TipoElemento)
DEVUELVE Booleano 
bajo := 1; 
alto := n; 
encontrado := CIERTO; 
REPETIR 
 medio := (bajo + alto) DIV 2; 
 SI v(medio) = buscado ENTONCES 
encontrado := CIERTO; 
 SI NO 
SI v(medio)<buscado ENTONCES 
 bajo := medio + 1; 
SI NO 
 alto := medio – 1; 
 HASTA QUE encontrado O bajo>alto; 
DEVOLVER encontrado; 
 3 
8) Algoritmo recursivo para buscar un elemento en un vector ordenado v con n elementos mediante 
búsqueda binaria. 
 
FUNCIÓN Pertenece(v:TipoVector; comienzo, final: TipoPosicion; 
buscado:TipoElemento) DEVUELVE Booleano 
 
 SI comienzo = final ENTONCES 
DEVOLVER v(comienzo)=buscado; 
 SI NO 
 medio := (comienzo + final) DIV 2; 
 SI buscado = v(medio) ENTONCES 
 DEVOLVER CIERTO 
 SI NO 
 SI buscado < v(medio) ENTONCES 
 DEVOLVER Pertenece(v,comienzo,medio-1,buscado) 
 SI NO 
 DEVOLVER Pertenece(v,medio+1,final,buscado) 
 
 
9) Algoritmo iterativo para hallar el factorial de un número natural n 
 
fact := 1; 
PARA i DESDE 1 HASTA n HACER 
 fact := fact * i; 
 
10) Algoritmo recursivo para hallar el factorial de un número natural n 
 
FUNCIÓN Factorial (n: Natural) DEVUELVE Natural 
SI n=0 ENTONCES 
 DEVOLVER 1; 
SI NO 
 DEVOLVER n*Factorial(n-1); 
 
 
11) Algoritmo para hallar el n-ésimo elemento de la sucesión de Fibonacci 
 
La sucesión de Fibonacci se define, para números naturales, de la siguiente forma: 
 






e.o.c)2Fibonacci()1Fibonacci(
1 si1
)Fibonacci(
n-n-
n
n 
 
Un algoritmo para calcular el n-ésimo término de la sucesión es el siguiente: 
 
SI n<=1 ENTONCES 
 fib_n := 1; 
SI NO 
 fib_menor := 1; 
 fib_mayor := 1; 
 PARA i DESDE 2 HASTA n HACER 
 aux := fib_menor; 
 fib_menor := fib_mayor; 
 fib_mayor := aux + fib_mayor; 
 fib_n := fib_mayor; 
Estructura de Datos/Practicas y ejercicios/Informacion de la reserva de NIIRONENORDUNA - ALBERTO SEBASTIAN - YL9PIR.pdf
Gracias por volar con Norwegian
 
Norwegian Air Shuttle - PB 115, N-1366 Lysaker, Noruega - Tel: 815 21 815 - Número Org.: NO 965 920 358 MVA - http://www.norwegian.com/
IVA no. Dinamarca CVR-/SE nr.32083927 / Suecia SE 516405399201 / Finlandia FI 23617257 / Francia FR 03 810456822 / UK 159 6755 56 / España N0282664B
NIIRONENORDUNA/ALBERTO SEBASTIAN 
Helsinki - Madrid 
D86151 - 24 ago 2016 - 13:55 - LowFare 
	
Travel Document - Información de la Reserva
	
Booking reference Número de reserva YL9PIR
Passenger Pasajero NIIRONENORDUNA/ALBERTO SEBASTIAN
Flight Vuelo D86151 - 24 ago 2016
Departure Salida 13:55 Helsinki (HEL) Terminal 2
Arrival Llegada 17:10 Madrid (MAD) Terminal 2
Seat Asiento No seat reservation /Sin reserva de asiento
Cabin baggage Equipaje de mano x 1, 10 Max kg, Max 55 x 40 x 23 cm
Checked baggage Equipaje facturado x 1, 20 Max kg, por maleta
Price category Tipo de tarifa LowFare/LowFare
Document number Número de documento 328-7201683923
Comment Comentario Printed/Impreso - 08 jul 2016
	
Información importante Cómo cambiar una reserva
Todos los pasajeros deberán presentar un documento identificativo válido y los
documentos de viaje para todos los vuelos. Para información específica sobre estos
requisitos, contacte con las autoridades pertinentes (por ejemplo, embajada/consulado).
 
 
¿Viaja solo con equipaje de mano? Vaya directo a la puerta de embarque cuando viaje
dentro de los países nórdicos o de los países nórdicos a Europa (excepto Reino Unido).
Todos los equipajes debe ser etiquetados con el nombre, la dirección y el teléfono del
pasajero.
 
Los mostradores de facturación abren 2 horas antes de la hora de salida programada (3
horas para los vuelos hacia/desde Dubái, Israel, Tailandia, Caribe y Estados Unidos).
Los mostradores de facturación (incl. la facturación de equipaje) cierran 30 minutos
antes de la hora de salida en vuelos domésticos (países nórdicos), 1 hora antes en
vuelos hacia/desde Dubái, Israel, Tailandia, Caribe y Estados Unidos, y 45 minutos
antes para el resto de vuelos. NOTA: Pasajeros con necesidades especiales, equipajes
especiales y menores no acompañados deberán hacer el check-in al menos 1 hora
antes de la hora de salida programada.
 
Los pasajeros deben presentarse en la puerta de embarque al menos 20 minutos antes
de la salida programada para vuelos dentro de los países nórdicos y 30 minutos antes
para el resto de vuelos.
 
Los cambios se pueden realizar hasta 30 minutos antes de la hora de salida
programada. Se aplicarán los cargos correspondientes. Los cambios pueden hacerse
online a través de Mis Reservas. Se aplicará un cargo adicional a los cambios
realizados a través de nuestro Call Center o en el aeropuerto.
 
Condiciones diferentes pueden aplicarse a los billetes reservados como parte de un
paquete hotel/vuelo y/o a través de una agencia de viajes. Otros términos y condiciones
también se aplican a las reservas de grupos. Consulte
http://www.norwegian.com/en/flight/group-travel/
 
Servicios de Internet
www.norwegian.no / www.norwegian.se / www.norwegian.dk/ www.norwegian.com
 
Servicios móviles (en noruego)
m.norwegian.no
 
Call Center: 24 horas, 7 días a la semana
Noruega: 815 21 815 (+47 21 49 00 15 desde el extranjero)
Suecia: +46 (0) 770 45 77 00 Finlandia: +358 (0) 9 2310 1600
Dinamarca: +45 70 80 78 80
Estados Unidos: 1-800-357-4159
 
A menos que se indique lo contratio, este vuelo será operado por Norwegian Air
Shuttle, Norwegian Air International o Norwegian Air Norway en nombre de Norwegian
Air Shuttle.
Para términos y condiciones, visite www.norwegian.com
 
Estructura de Datos/Practicas y ejercicios/Practica 0.pdf
Práctica 0. Punteros 
Estructuras de Datos 
 
Objetivo 
Se trata de que el alumno empiece a familiarizarse con los punteros en Pascal. 
 
Enunciado 
Una empresa con ciertas dificultades económicas quiere tener un registro de empleados para 
poder procesar la información relativa a su sueldo más fácilmente y así saber si tiene que 
reasignar a empleados a diferentes departamentos medidas. 
 
De cada empleado se quiere guardar su nombre, su edad y su sueldo, por lo que se tendrá un 
registro de N empleados que tiene la empresa. El objetivo es ordenar la información en orden 
ascendente de acuerdo al salario de cada uno, pero para hacerlo más eficiente, en lugar de 
almacenar éstos en un array de empleados, se tendrá un array de punteros a empleados, para 
que cada vez que haya movimiento en la ordenación, no se hagan continuamente copias de los 
datos sino que se cambien los punteros, resultando así más eficiente. La Figura 1 ilustra el 
posible intercambio de punteros. 
 
 
Figura 1. Ordenar la información de los empleados 
 
Lo que se pide es, crear un programa que haga lo siguiente: 
 Crear los diferentes empleados, para lo cual pedirá los datos por teclado. 
 Mostrar por pantalla el listado de los empleados de la empresa. 
 Ordenar los empleados en función de su sueldo (de menor a mayor). 
 Mostrar por pantalla el listado de empleados ordenado. 
 Eliminar del registro aquellos empleados que superen un salario determinado. 
 Mostrar por pantalla el registro de empleados. 
Estructura de Datos/Practicas y ejercicios/Practica1_costecomputacional.pdf
Práctica 0c: Análisis de rendimiento y complejidad 
Estructuras de Datos – 1º GII/GIS 
 
 
En esta práctica se desea evaluar el coste computacional de diversos algoritmos midiendo 
tiempos de ejecución para diferentes tamaños de problema. 
 
Para ello será necesario hacer uso de la unidad de Pascal Sysutils. Las unidades en Pascal se 
pueden utilizar para importar a un proyecto tipos y subprogramas previamente creados y 
compilados
1
. Para utilizar una unidad en un programa principal (u otra unidad) basta invocar 
“USES NombreUnidad;” en la cabecera del módulo, de manera que para utilizar las 
definiciones de Sysutils sería necesario escribir algo como: 
 
PROGRAM Complejidad; 
USES Sysutils; 
 
Una vez importada la unidad tendremos disponibles una variedad muy interesante de 
subprogramas que tienen que ver
con funcionalidad del sistema (ficheros, cadenas de 
caracteres, funcionalidad horaria, etc.
2
). Para el propósito de esta práctica se utilizará la parte 
específica de la unidad dedicada a funcionalidad de manejo de variables temporales y fechas: 
http://www.freepascal.org/docs-html/rtl/sysutils/datetimeroutines.html 
 
En particular, se puede observar el prototipo de la función Now y la función 
DateTimeToTimeStamp: 
 
 
 
 
 
 
1
 La creación de unidades será motivo de las próximas prácticas. 
2
 Más información en: http://www.freepascal.org/docs-html/rtl/sysutils/index-5.html 
http://www.freepascal.org/docs-html/rtl/sysutils/datetimeroutines.html
http://www.freepascal.org/docs-html/rtl/sysutils/index-5.html
 
Como se puede comprobar, la llamada a la función Now no recibe argumentos y devuelve un 
valor de tipo TDateTime que representa la fecha y hora en un valor numérico de doble 
precisión. Este tipo puede ser descompuesto en TTimeStamp, más manejable, a través de la 
función DateTimeToTimeStamp. El tipo TTimeStamp es un registro con campos Date y 
Time como fecha y hora del sistema, y representados por sendos LongInt. 
 
Si la fecha no nos interesa porque queremos cronometrar simplemente porciones de código en 
ejecución nos bastaría la parte de tipo Time, que como a cualquier registro se accede a través 
de la notación “.” como registro.time. 
 
Por ejemplo considérese el siguiente código: 
 
PROGRAM Complejidad; 
USES Sysutils; 
CONST 
N = 1000000; 
VAR 
ts, ts2: TTimeStamp; 
i, x: longint; 
BEGIN 
ts := DateTimeToTimeStamp(Now); 
x := 0; 
FOR i := 1 TO N DO 
x := x + 1; 
ts2 := DateTimeToTimeStamp (Now); 
writeln('tiempo: ',ts2.time - ts.time, ' ms'); 
END. 
 
A partir de aquí ya es posible evaluar el coste computacional de diferentes algoritmos para 
diferentes tamaños de problema. Los tiempos que devuelvan serán posteriormente 
representados en una gráfica N-T (tamaño del problema, N, en abscisas y tiempo, T, en 
ordenadas). Por ejemplo para unas ejecuciones con diversos valores de la constante podemos 
obtener los siguientes resultados
3
: 
 
 
 
N Tiempo (ms) 
10.000.000 55 
100.000.000 191 
1000.000.000 1871 
5.000.000.000 9312 
7.000.000.000 13084 
1E+10 18584 
 
 
Se pide hacer en Pascal un cuerpo de programa principal que utilice un tipo Array definido por 
el usuario del siguiente modo: 
 
 
3
 Para este ejemplo se ha hecho uso de un doble bucle porque la variable iteradora sólo admite valores del rango 
longint (32 bits, hasta 2
31
-1 =~ 2147 millones ). Existe el tipo Cardinal para aumentar a unos 4000 millones. 
0
2000
4000
6000
8000
10000
12000
14000
16000
18000
20000
0 2E+09 4E+09 6E+09 8E+09 1E+10
T (ms) 
N 
const 
N = 1048576; {2^20} 
type 
TAlmacen = array [1..N] of integer; 
var 
coleccion: TAlmacen; 
 
A continuación codifique 4 subprogramas: 
1) Búsqueda secuencial (O(n)): itera a lo largo del array hasta encontrar el elemento que 
se busca. En el peor de los casos nunca lo encuentra: 
 
function Busqueda_secuencial(var c: TAlmacen): boolean; 
 
2) Busqueda binaria (O(log n)): en un array previamente ordenado busca un elemento 
comenzando por la posición central del array y evaluando si se ha encontrado, si no, 
sigue buscando en la mitad restante que interese (mitad mayor o mitad menor). En el 
peor de los casos nunca lo encuentra. 
3) Ordenación directa (O(n2)): se realiza mediante 2 bucles (ordenación por intercambio 
directo, inserción directa, etc.), por ejemplo haciendo N pasadas de intercambios entre 
elementos vecinos (siendo N el tamaño del array). 
4) Ordenación por mezcla (O(n log n)): algoritmo multipasada. En la primera pasada se 
ordena un elemento con su respectivo vecino (longitud 1) “recorriendo ambas 
posiciones por separado” (elementos en posiciones i e i+1, siendo i mod 2 = 0, 
ordenando 2 elementos entre sí), en la segunda pasada el array está ordenado por 
parejas y se ordenan dobles parejas mediante 2 recorridos de 2 elementos (longitud 2, 
ordena 4 elementos entre sí), en la siguiente pasada igual con 2 recorridos sobre 4 
elementos (longitud 4, ordenando 8 elementos entre sí), y así sucesivamente hasta 
terminar con 2 recorridos de cada mitad de elementos del array (longitud N/2) para 
ordenar todos los valores. Ejemplo: 
 
Recorridos de longitud 1: 
6 3 8 5 2 9 7 4 
 
3 6 5 8 2 9 4 7 
 
Recorridos de longitud 2: 
3 6 5 8 2 9 4 7 
 
3 5 6 8 2 4 7 9 
 
Recorridos de longitud 4: 
3 5 6 8 2 4 7 9 
 
2 3 4 5 6 7 8 9 
 
 
A continuación mide el tiempo (T) invertido con cada subprograma probando con diferentes 
tamaños del array (N) definido anteriormente y haz una representación gráfica de cada 
comportamiento. 
 
Estructura de Datos/Practicas y ejercicios/Practica4b_listas.pdf
Práctica 4b - Listas 
Estructuras de Datos 
 
 
En esta práctica se profundizará más sobre el aprendizaje de listas, implementando 
algunas de sus posibles versiones, para después hacer uso de las mismas. La práctica 
consta de dos partes: 
 
Primera parte 
 
El comportamiento de un TAD Lista viene determinado por su especificación formal. 
Siguiendo la especificación formal vista en clase se pide implementar lo siguiente: 
 
a) Implementación de la unidad uListaEst, como una lista estática que simule 
memoria dinámica utilizando un array como almacén para guardar los nodos. 
b) Implementación de la unidad uListCircular como una lista circular con 
enlace simple y puntero al último elemento. Una posible representación gráfica 
se puede ver a continuación: 
 
 
 
 
 
 
 
 
En ambos casos los elementos de las listas serán de tipo TElem, cuyo TAD estará 
definido en una unidad diferente (uElem). 
 
Segunda parte 
 
Se quiere comprobar si una subcadena está contenida dentro de una cadena. Dado que el 
tipo para representar cadenas en Pascal es el tipo String, que tiene un tamaño máximo y 
se quiere poder utilizar cadenas de cualquier tamaño sin tener ningún tipo de limitación, 
se opta por representar las cadenas mediante listas, donde cada elemento de la lista será 
un carácter (el TElem será de tipo Char en este caso). Así, la posible secuencia de 
acciones que debe tener el programa que se pide es la siguiente: 
 
 
1. Crear la cadena (crear una lista con el contenido de la cadena). 
2. Crear la subcadena (crear una lista con el contenido de la subcadena). 
3. Comprobar si la subcadena está contenida en la cadena. 
4. Eliminar ambas cadenas (eliminar las dos listas). 
 
 
Se deberá extender el TAD TListaEst y TListaCircular para añadir la operación 
de poder recuperar el elemento que se encuentre en una posición determinada de la lista. 
A continuación, se presenta la especificación algebraica para dicha operación: 
 
 
 
 
lista 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Un ejemplo de salida de diferentes ejecuciones se presenta a continuación: 
 
 
 
 
 
 
Nota 1: Se considera necesario un nivel elevado de encapsulación y abstracción. 
 
Nota 2: Se hará uso de las normas de estilo dictadas en clase (cabecera del fichero, interfaz de la unidad 
con precondiciones, postcondiciones, excepciones, implementaciones con el análisis de complejidad de 
cada operación, nombres coherentes de variables y operaciones,...) 
 
Plantilla de cabecera del fichero: 
{********************************************************************************* 
* * 
* Módulo: * 
* Tipo: Programa() Interfaz-Implementación TAD () Otros() * 
* Autor/es: * 
* Fecha de actualización: * 
* Descripción: * 
* * 
**********************************************************************************} 
*********************************************************************************} 
La cadena [n,o,c] SI está contenida en la cadena [r,i,n,o,c,e,r,o,n,t,e] 
La cadena
[n,o,c] NO está contenida en la cadena [c,a,s,a] 
La cadena [p,e,p,e] SI está contenida en la cadena [h,o,l,a, ,p,e,p,e] 
… 
OPERACIONES 
 
(* operación observadora no selectora *) 
PARCIAL GetElemPos: TipoLista x Natural  TipoElemento 
 
VARIABLES 
 lista: TipoLista; 
 p: Natural; 
 
ECUACIONES DE DEFINITUD 
 SI ((p > 0) Y (p <= Longitud(lista))  
 DEF (GetElemPos (lista, p)) 
ECUACIONES 
GetElemPos(Construir(e, lista), p) = SI p=1  
e 
 | GetElemPos (lista, p-1) 
… 
Estructura de Datos/Practicas y ejercicios/PracticaArbolesNew.pdf
Práctica Árboles Binarios de Búsqueda
Estructuras de Datos
Implementación del árbol binario de búsqueda
Crearemos la unidad UArbolBB que implemente el TAD Árbol Binario de Búsqueda
respetando la ya conocida especificación algebraica.
ESPECIFICACIÓN ArbolBinarioBusqueda
 PARÁMETROS GENÉRICOS
 TIPOS TipoElemento
 FIN PARÁMETROS
 TIPOS TipoArbolBin
 OPERACIONES
 (* constructoras generadoras *)
CrearArbolBinVacio: à TipoArbolBin
ConstruirArbolBin: TipoArbolBin x TipoElemento x TipoArbolBin à TipoArbolBin
 (* observadoras selectoras *)
PARCIAL Raiz: TipoArbolBin à TipoElemento
PARCIAL HijoIzdo: TipoArbolBin à TipoArbolBin
PARCIAL HijoDcho: TipoArbolBin à TipoArbolBin
 (* observadoras no selectoras *)
EsArbolBinVacio: TipoArbolBin à Booleano
PARAMETROS GENERICOS
 OPERACIONES
 Mayor: TipoElemento x TipoElemento à Booleano
FIN PARAMETROS
Pertenece: TipoArbolBin x TipoElemento à Booleano
PARCIAL Minimo: TipoArbolBin à TipoElemento
(* constructoras no generadoras *)
Insertar: TipoElemento x TipoArbolBin à TipoArbolBin
Eliminar: TipoElemento x TipoArbolBin à TipoArbolBin
VARIABLES
r, e: TipoElemento;
i, d: TipoArbolBin;
ECUACIONES DE DEFINITUD
DEF(Minimo(ConstruirArbolBin(i, r, d)))
DEF(Raiz(ConstruirArbolBin(i, r, d)))
DEF(HijoIzdo(ConstruirArbolBin(i, r, d)))
DEF(HijoDcho(ConstruirArbolBin(i, r, d)))
ECUACIONES
(* observadoras selectoras *)
Raiz(ConstruirArbolBin(i, r, d)) = r
HijoIzq(ConstruirArbolBin(i, r, d)) = i
HijoDer(ConstruirArbolBin(i, r, d)) = d
(* observadoras no selectoras *)
Pertenece (e, CrearArbolBinVacio) = FALSO
Pertenece (e, ConstruirArbonBin(i, r, d)) = SI e=r à
CIERTO
 | SI Mayor(e, r) à
Pertenece(e, d)
 | Pertenece(e, i)
Minimo(ConstruirArbolBin(i, r, d)) =
 SI EsArbolBinVacio(i) à
 r
 | Minimo(i)
EsArbolBinVacio(CrearArbolBinVacio) = CIERTO
EsArbolBinVacio(ConstruirArbolBin(i, r, d)) = FALSO
(* constructoras no generadoras *)
Insertar(e, CrearArbolBinVacio) = ConstruirArbolBin(CrearArbolBinVacio, e, CrearArbolBinVacio)
Insertar(e,ConstruirArbolBin(i, r, d)) = SI (e = r) à
ConstruirArbolBin(i, r, d)
 | SI Mayor(e, r) à
ConstruirArbolBin(i, r, Insertar(e, d))
 | ConstruirArbolBin(Insertar(e, i), r, d)
Eliminar(e, CrearArbolBinVacio) = CrearArbolBinVacio
Eliminar(e, ConstruirArbolBin(i, r, d)) =
 SI (e = r) à
 SI EsArbolBinVacio(d) à
 i
 | ConstruirArbolBin(i, Minimo(d), Eliminar(Minimo(d), d))
 | SI Mayor(e, r) à
 ConstruirArbolBin(i, r, Eliminar(e, d))
 | ConstruirArbolBin(Eliminar(e, i), r, d)
FIN ESPECIFICACION
Uso del árbol binario de búsqueda
Para probar la utilidad del árbol binario se pide desarrollar un programa que clasifique una
lista de tweets por los hashtags que aparecen en ellos. Un tweet es una publicación o
actualización de estado realizada en la red social Twitter. Un tweet es un mensaje de texto
con extensión máxima de 140 caracteres (están permitidos letras, números, signos y
enlaces). Los tweets pueden contener hashtags o etiquetas, que permiten establecer el tema
del que trata el tweet. Hashtag es una palabra compuesta por hash (almohadilla) y tag
(etiqueta) y son palabras que empiezan por el símbolo almohadilla (#), seguido de una
palabra (por ejemplo: #programación, #cloud, etc.). 
Para el desarrollo de la práctica se proporcionan dos ficheros de texto: 
- hashtags.txt, que almacena un hashtag en cada línea
- tweets.txt, que almacena un tweet en cada línea
El etiquetado de tweets lo vamos a implementar como un árbol binario de búsqueda en el
que cada nodo almacene un registro con dos campos:
- hashtag: que almacena un solo hashtag.
- listaTweets: que almacena una lista dinámica de tweets que contengan este
hashtag. La lista debe ser dinámica, ya que no conocemos a priori el número de tweets que
van a contener cada hashtag. Puedes utilizar una implementación de listas que tengas ya
hecha.
Esta representación y la funcionalidad asociada deberá ir implementada en una unidad que
se utilizará como el TipoElemento del árbol binario de búsqueda.
De modo que lo que se pide es:
1.- Construir la estructura fundamental del ABB: para ello, leer la lista de hashtags
proporcionada en hashtags.txt (cada tweet es una línea del fichero de texto) y construir el
árbol binario de búsqueda de hashtags ordenado por orden alfabético. Para la construcción
del ABB, recuerda que sólo debes utilizar la interfaz de la unidad UArbolBB.
2.- Etiquetado de tweets: Una vez construido el árbol, leer cada uno de los tweets
almacenados en tweets.txt (cada tweet es una línea del fichero de texto). Para cada tweet,
buscar los hashtags que contenga y almacenar el tweet en el nodo del ABB que
corresponda al hashtag. Por ejemplo, un tweet como el siguiente 'Sería feliz estando todo
el tiempo de #viajesPorElMundo' debería estar almacenado en la listaTweets del
nodo cuyo valor del campo hashtag coincida con '#viajesPorElMundo'. Por otro lado,
puede suceder que un tweet contenga más de un hastag.
3.- Consultas: como resultado, hemos construido una base de datos de juguete y podemos
implementar la funcionalidad que permita realizar consultas de tweets por hashtag. Es
decir, el usuario podrá preguntar por un hashtag cualquiera y el programa deberá
responder con la impresión por pantalla de los tweets que contienen el hashtag consultado
o, en su caso, que no se ha encontrado ningún tweet con ese hashtag.
4.- ¿Qué diferencia habría si en lugar de un árbol binario de búsqueda utilizamos una lista?
Funciones útiles:
Para el manejo de cadenas, se recomienda el uso de la unidad sysutils y strutils.
En concreto:
- ansicomparetext(s1,s2): función que compara los strings s1 y s2. Si s1=s2
devuelve 0, Si s1<s2, devuelve un entero negativo y si s1>s2, devuelve un entero
positivo. Está en sysutils.
- posEx(c,s): función que devuelve la posición del carácter c dentro de la cadena s.
Está en strutils.
- ExtractSubstr(s,p,delim): función que recibe una cadena s, una posición p y
un conjunto de delimitadores delim y devuelve la palabra que empieza en la posición p de
s. Nota: delim debe ser declarada como una variable de tipo TSysCharSet e
inicializada como delim := [' ']. Está en strutils.
Nota: Como siempre, se hará uso de las normas de estilo dictadas en clase (cabecera del fichero, interfaz de la unidad
con precondiciones, postcondiciones, excepciones, implementaciones con el análisis de complejidad de cada operación,
nombres coherentes de variables y operaciones,...)
Plantilla de cabecera del fichero:
{*********************************************************************************
* Módulo: *
* Tipo: Programa() Interfaz-Implementación TAD () Otros() *
* Autor/es: *
* Fecha de actualización: *
* Descripción: *
*********************************************************************************}
Nino
Resaltado
Arbol Binario de Busqueda
	PARÁMETROS GENÉRICOS
	FIN PARÁMETROS
	OPERACIONES
	VARIABLES
	ECUACIONES DE DEFINITUD
	ECUACIONES
	FIN ESPECIFICACION
Estructura de Datos/Practicas y ejercicios/PracticaGrafosNew.pdf
Práctica Grafos
Estructuras de Datos
Implementación de la unidad grafo
Crearemos la unidad UGrafo que implemente el TAD Grafo. El grao que esperamos
utilizar en esta ocasión es disperso, conexo y no dirigido. El alumno, con estos datos,
debe decidir cuál es la implementación más adecuada.
La interfaz de la unidad debe
permitir la construcción de cualquier grafo. Se sugiere que la unidad grafo disponga de, al
menos, la siguiente funcionalidad accesible en su interfaz:
PROCEDURE CrearGrafoVacio(VAR g:TGrafo);
PROCEDURE InsertarOrigen(VAR g:TGrafo; origen:TElemento);
PROCEDURE InsertarDestino(g:TGrafo; origen:TElemento; destino: 
TElemento);
FUNCTION EsGrafoVacio(g:TGrafo):Boolean;
FUNCTION PerteneceAOrigenes(g:TGrafo; origen:TElemento):Boolean;
FUNCTION PerteneceADestinos(g:TGrafo; origen:TElemento; destino: 
TElemento):Boolean;
PROCEDURE ListaAdyacencia(g:TGrafo; e:TElemento; VAR adyacentes:TLista);
Uso de la unidad grafo
El Metro de Madrid puede representarse como un grafo, en el que las estaciones son los
vértices y las conexiones entre ellas, las aristas. Por ejemplo, una estación como Sol, tiene
seis estaciones adyacentes: Ópera, Sevilla, Callao, Lavapies, Gran Vía y Tirso de Molina
(las dos primeras son de la línea 2, las dos siguiente de la línea 3 y las dos últimas de la
línea 1). Se puede consultar un plano del metro en la siguiente URL:
https://www.metromadrid.es/export/sites/metro/comun/documentos/planos/Planoesquemat
icoespanol.pdf
Para probar la funcionalidad de nuestra implementación del TAD grafo, vamos a modelar
con ella el Metro de Madrid. Para ello, se proporcionan 12 ficheros de texto (desde L01.txt
hasta L12.txt, en formato UTF8, de modo que si utilizas windows, quizá necesites paarlos
a formato ASCII), uno por cada línea de metro, en los que se listan las estaciones que las
componen, una por cada línea del fichero. Se debe observar que las líneas circulares (6 y
12) aparecen con estructura lineal en el archivo, pero nos resultarán igualmente útiles de
esa manera.
Se pide implementar la siguiente funcionalidad:
1.- Construir el grafo del Metro de Madrid: para ello, se debe leer la lista de estaciones de
cada archivo proporcionado. Cada una de las estaciones debe tener al menos los datos de
su nombre y el/los número/s identificativo/s de la/s línea/s a la/s que pertenece. Para la
construcción del grafo, recuerda que debes utilizar exclusivamente la interfaz de la unidad
Ugrafo.
2.- Consultar estaciones: desde el programa principal, permitir al usuario realizar
consultas por estaciones. Para cada estación, se debe mostrar si existe o no en el grafo y,
en caso de existir, las líneas a las que pertenece y las estaciones adyacentes.
3.- Recorrido: Implementar en la unidad UGrafo un recorrido en anchura desde un
origen dado. El recorrido en anchura de un grafo parte de un vértice dado A (cualquiera) y
explora en primer lugar todos los vértices adyacentes. Luego toma uno de esos vértices y
explora todos sus adyacentes no visitados previamente, luego desde otro adyacente del
origen A ya visitado en primera iteración se exploran todos sus adyacentes no visitados en
pasos anteriores y así sucesivamente. Para mantener memoria de los vértices que debemos
https://www.metromadrid.es/export/sites/metro/comun/documentos/planos/Planoesquematicoespanol.pdf
https://www.metromadrid.es/export/sites/metro/comun/documentos/planos/Planoesquematicoespanol.pdf
visitar en cada paso se utilizará una estructura FIFO, y para evitar entrar en ciclos y
revisitar vértices ya visitados previamente se utilizará un conjunto de vértices visitados.
Seguro que ya tienes implementadas estas estructuras auxiliares. Si es así, utiliza esas
implementaciones, recordando ser muy cuidadoso y acceder a su funcionalidad
exclusivamente desde la interfaz proporcionada.
4.- Camino: Implementar también en la unidad UGrafo la funcionalidad necesaria para el
cálculo de un camino entre un vértice origen y un vértice destino (no importa si es de
longitud mínima o no).
Nota: Como siempre, se hará uso de las normas de estilo dictadas en clase (cabecera del fichero, interfaz de la unidad
con precondiciones, postcondiciones, excepciones, implementaciones con el análisis de complejidad de cada operación,
nombres coherentes de variables y operaciones,...)
Plantilla de cabecera del fichero:
{*********************************************************************************
* Módulo: *
* Tipo: Programa() Interfaz-Implementación TAD () Otros() *
* Autor/es: *
* Fecha de actualización: *
* Descripción: *
*********************************************************************************}
Estructura de Datos/Practicas y ejercicios/Practica_1_complejos_vicalvaro.pdf
Práctica 1. Uso de TADs 
Estructuras de Datos 
 
Objetivo: 
Crear la unidad en Pascal que defina el TAD de números complejos, con las siguientes 
operaciones: 
OPERACIONES 
 (* constructoras generadoras *) 
CrearComplejo: Real x Real  TipoComplejo 
 (* observadoras selectoras *) 
ParteReal: TipoComplejo  Real 
ParteImaginaria: TipoComplejo  Real 
 (* observadoras no selectoras *) 
Modulo: TipoComplejo  Real 
 (* constructora no generadora *) 
Conjugado: TipoComplejo  TipoComplejo 
Sumar: TipoComplejo x TipoComplejo  TipoComplejo 
Restar: TipoComplejo x TipoComplejo  TipoComplejo 
Multiplicar: TipoComplejo x TipoComplejo  TipoComplejo 
Dividir: TipoComplejo x TipoComplejo  TipoComplejo 
 
Se recuerda que las fórmulas para el manejo de números complejos son: 
Número complejo: 
z = (re, im) 
Suma de números complejos: 
 212121 , imimrerezz  
Resta de números complejos: 
 212121 , imimrerezz  
Producto de números complejos: 
 2121212121 , imrereimimimrerezz  
Cociente de números complejos: 













2
2
2
2
2121
2
2
2
2
2121
2
1 ,
imre
imrereim
imre
imimrere
z
z
 
Módulo de un número complejo: 
22 imrez  
Conjugado de un número complejo (dado z por la primera definición): 
),( imrez  
Seguidamente crear la implementación de otra unidad que defina una extensión del TAD 
TipoComplejo con la que podamos calcular los parámetros en un circuito eléctrico RCL en 
serie. La Ley de Ohm puede generalizarse para corriente alterna si hacemos una analogía entre 
la resistencia de un circuito de corriente continua y las impedancias en corriente alterna. Para 
el cálculo tanto de las impedancias de los componentes individuales del circuito, como de las 
caídas de potencial en cada componente, frecuencia de resonancia del circuito,... haremos uso 
de las operaciones que habíamos implementado para el manejo de variables TipoComplejo. 
ImpedanciaL: Real X Real  TipoComplejo 
ImpedanciaR: Real  TipoComplejo 
ImpedanciaC: Real X Real  TipoComplejo 
ImpedanciaTotal: TipoComplejo X TipoComplejo X TipoComplejo  TipoComplejo 
FrecuenciaAngular: Real  Real 
Intensidad: TipoComplejo X TipoComplejo  TipoComplejo 
CaidaPotencial: TipoComplejo X TipoComplejo  TipoComplejo 
 
 
Relación entre la frecuencia y la frecuencia angular: 
 2 
Impedancia Resistiva: 
RZR  
Impedancia Capacitiva: 
C
j
Cj
ZC



1 
Impedancia Inductiva: 
LjZL  
Ley de Ohm: 
ZIV  
A continuación crearemos un programa principal que haga uso de las unidades anteriores para 
resolver el siguiente problema (cálculo de caídas de potencial en cada dispositivo del circuito): 
Dado un circuito RCL en serie y una fuente alterna (ver figura superior) se pide realizar un 
programa que permita calcular el potencial en cada uno de los puntos A, B, C y D para valores 
coherentes de V0, , C, L y R (por ejemplo 220V, 50Hz, 1.2 µF, 3 mHr, 5 k). 
Estructura de Datos/Practicas y ejercicios/Practica_5_pilasColas.pdf
Práctica 5. Pilas y Colas 
Estructuras de Datos 
 
Objetivo: 
Implementación de las unidades de Pilas y Colas en versión estática y dinámica. 
 
En esta práctica tendremos que hacer 4 unidades para la realización de Pilas y Colas (2 versiones de 
cada una, estática y dinámica), así como una unidad para definir el TipoElemento. 
 
Unidades Pila: 
Versión estática: usaremos la versión de Pila con un array parcialmente lleno como 
almacén y un índice Cima (0..MAX). 
Versión dinámica:
usaremos una versión de lista enlazada simple con un único puntero de 
enlace y referencia a la estructura. 
Unidades Cola: 
Versión estática: implementaremos la versión circular con un array de dimensión 
predeterminada. 
Versión dinámica: También haremos una versión circular, puesto que en listas ya se pidió 
la realización de estructura lineal doblemente enlazada con puntero cabecera y final. 
 
Para el caso del TipoElemento simularemos una imagen como un array de 640x480 posiciones 
(píxeles) y valores de tipo Byte (primitivo en Pascal) comprendidos entre 0-255. En el contexto de 
una imagen un píxel con valor de 0 representa un tono negro, y uno con un valor de 255 representa 
un tono blanco. Valores intermedios entre 0 y 255 describen tonos grisáceos, más claros cuanto 
mayor es el valor hasta llegar a 255. 
 
 
 
 
 
 
 
 
 
 
 
 
 
Figura 1: Definción del TipoElemento como una simulación de imagen. 
 
Un vídeo no es otra cosa que una secuencia de imágenes. Por ejemplo, un vídeo consistente en 10 
imágenes o fotogramas es una secuencia de 10 imágenes. Se pide: 
(a) Generar un vídeo de 10 imágenes y almacenarlo en una estructura de cola, llamada videoFwd. 
Los valores de intensidad de los píxeles se pueden generar de manera aleatoria entre 0 y 255, con 
valores fijos para cada imagen, o de la manera que tú elijas. 
(b) Con ayuda de una estructura intermedia de tipo pila, generar otro vídeo y guardarlo en otra 
estructura cola llamada videoRev que contenga los mismos fotogramas que videoFwd, pero 
colocados en orden inverso. 
(c) Como parte opcional, se propone representar gráficamente el vídeo, utilizando los conceptos 
aprendidos en la práctica de Mandelbrot. 
 
unit uElemento; 
interface 
const 
 MAX_RES_X = 640; 
 MAX_RES_Y = 480; 
type 
 TipoElemento = TImagen; 
 TImagen = array[1..640, 1..480] of byte; 
… 
Implementation 
… 
end. 
Estructura de Datos/Practicas y ejercicios/Practica_listas.pdf
Práctica Listas
Estructuras de Datos
El comportamiento de un TAD Lista viene determinado por su especificación formal,
que se muestra a continuación:
ESPECIFICACIÓN Listas
PARÁMETROS FORMALES
TIPOS TipoElemento
FIN PARAMETROS
TIPOS TipoLista
OPERACIONES
(* operaciones constructoras generadoras *)
CrearVacia:  TipoLista
Construir: TipoElemento x TipoLista  TipoLista
(* operaciones observadoras selectoras *)
PARCIAL Primero: TipoLista  TipoElemento
PARCIAL Resto: TipoLista  TipoLista
(* operaciones observadoras no selectoras *)
EsVacia: TipoLista  Booleano
Longitud: TipoLista  Natural
PARCIAL Ultimo: TipoLista  TipoElemento
Pertenece: TipoElemento x TipoLista  Booleano
(* operaciones constructoras no generadoras *)
Concatenar: TipoLista x TipoLista  TipoLista
BorrarElemento: TipoElemento x TipoLista TipoLista
InsertarFinal: TipoElemento x TipoLista  TipoLista
VARIABLES
lista, lista2: TipoLista;
e, e’: TipoElemento;
ECUACIONES DE DEFINITUD
DEF(Primero (Construir (e, lista)))
DEF(Resto (Construir (e, lista)))
DEF(Ultimo (Construir (e, lista)))
ECUACIONES
(* operaciones observadoras selectoras *)
Primero (Construir (e, lista)) = e
Resto (Construir (e, lista)) = lista
(* operaciones observadoras no selectoras *)
EsVacia (CrearVacia) = CIERTO
EsVacia (Construir (e, lista)) = FALSO
Longitud (CrearVacia) = 0
Longitud (Construir (e, lista)) = 1 + Longitud (lista)
Ultimo (Construir (e, lista)) = 
SI EsVacia(lista)  
e
SI NO 
Ultimo (lista)
Pertenece (e, CrearVacia) = FALSO
Pertenece  (e, Construir  (e’, lista))  =   (e = e’) O (Pertenece  (e,
lista))
(* operaciones constructoras no generadoras *)
Concatenar (CrearVacia, lista) = lista
Concatenar (Construir (e, lista), lista2) = 
Construir (e, Concatenar (lista, lista2))
BorrarElemento (e, CrearVacia) = CrearVacia
BorrarElemento (e, Construir (e’, lista)) = 
SI e = e’  
lista
SI NO 
Construir (e’, BorrarElemento (e, lista))
InsertarFinal (e, CrearVacia) = Construir (e, lista)
InsertarFinal   (e,   Construir   (e’,   l))   =   Construir   (e’,
InsertarFinal (e, l))
FIN ESPECIFICACIÓN Listas
Para manejar la implementación de listas, en esta práctica, se pide
a) Implementación de la unidad ListaDin, como una lista dinámica doble enlazada con puntero cabecera
y final.
b) Implementación de la unidad ListaEst, como una lista estática que simule memoria dinámica.
c) Diseñar un programa que lea un fichero binario con tipo base:
     TAlumno=RECORD
        expediente: integer;
        curso: integer;
        nombre: string;
        edad: integer;
        nota: real;
     END;
     TArchivo=FILE OF TAlumno;
y que a partir de los datos leídos en este archivo, por cada implementación, construya una lista de
elementos que contenga a todos los estudiantes y además implemente la funcionalidad necesaria para:
1) Determinar si un estudiante está matriculado.
2) Calcular la nota media de un curso.
3) Determinar el número de estudiantes aprobados por curso.
4) Conocer el nombre del estudiante con notas más elevadas.
5) Obtener el número de expediente del estudiante más joven. 
Nota 1: Se considera necesario un nivel elevado de encapsulación y abstracción.
 
Nota 2: Se hará uso de las normas de estilo dictadas en clase (cabecera del fichero, interfaz de la unidad
con precondiciones, postcondiciones, excepciones, implementaciones con el análisis de complejidad de
cada operación, nombres coherentes de variables y operaciones,...)
Plantilla de cabecera del fichero:
{*********************************************************************************
* *
* Módulo: *
* Tipo: Programa() Interfaz-Implementación TAD () Otros() *
* Autor/es: *
* Fecha de actualización: *
* Descripción: *
* *
*********************************************************************************}
Estructura de Datos/Practicas y ejercicios/Práctica 0b.pdf
Práctica 0.b. Punteros 
Estructuras de Datos 
 
Objetivo: 
Entender los motivos de eficiencia de la reserva de memoria dinámica y el paso de parámetros 
a subprogramas. 
Enunciado: 
Se pretende comprobar las limitaciones de los diferentes espacios de memoria mediante el 
uso de un subprograma recursivo que reserven en cada llamada un array de grandes 
dimensiones. 
Para ello se harán 2 versiones del subprograma, uno pasando por valor un array como 
parámetro (de tal manera que en cada llamada el sistema operativo reservará espacio para él 
en el stack de memoria), y otro pasando por valor un puntero con el que se reservará espacio 
para el array de grandes dimensiones mediante el operador NEW. 
Para controlar el número de llamadas recursivas que se hacen, en el cuerpo del subprograma 
se decrementará una variable entera que se pasará también como parámetro al subprograma 
recursivo. Cuando dicha variable alcance el valor de 0 pasará al caso base que no hará nada 
especial. 
De esta manera, las llamadas los respectivos subprogramas serían algo como: 
Subprograma(contenedor, 100); 
siendo contenedor un array por ejemplo de 20.000 elementos enteros (ocupará del orden 
de 20.000*4 Bytes ~ 80 KB) y el valor 100, por ejemplo, el número de llamadas recursivas que 
deben hacerse para llegar al caso base. 
Subprograma(puntContenedor, 10); 
siendo puntContenedor un puntero de tipo base array de los mismos 20.000 elementos 
enteros y el valor 100, nuevamente, el número de llamadas recursivas que deben hacerse 
para llegar al caso base. En cada llamada se reservará un array del mismo tamaño que el 
anterior. 
 
Estructura de Datos/Temario/Tema0_Punteros_New.pdf
TEMA 0 
Gestión de 
Memoria Dinámica 
ESTRUCTURAS DE DATOS 
1 
Objetivos 
 Tema preliminar para entender el uso de la herramienta 
básica en la gestión de memoria dinámica: punteros 
 
 Objetivos: 
◦ Conocer el concepto de “puntero” 
◦ Entender la gestión dinámica de memoria 
◦ Manejar estructuras estáticas y dinámicas en memoria a través de 
punteros 
◦ Crear y destruir estructuras dinámicas en memoria 
 
2 
Definición del problema
 Las estructuras estáticas (por ejemplo, array) no pueden 
cambiar su tamaño durante la ejecución del programa 
 Cambiar la disposición de los elementos dentro de la 
estructura estática es, a veces, costoso. 
 Ejemplos: 
◦ No se puede redimensionar un array. 
◦ Colocar el último elemento al comienzo del array. 
 Además, hay otros factores importantes a tener en cuenta 
sobre el uso de la memoria en los procesos. 
3 
Definición del problema 
 El espacio de memoria en un sistema está descompuesto 
de forma general en 4 bloques con tamaños diversos 
◦ Segmento de código: asignación automática 
◦ Variables globales: asignación automática 
◦ Stack o pila de memoria: asignación automática 
◦ Heap o montículo de memoria: asignación manual 
 
4 
Imagen extraída de: www.sw-at.com 
Stack 
Heap 
Global 
Código 
http://www.sw-at.com/blog/2011/03/23/where-does-code-execute-process-address-space-code-gvar-bss-heap-stack/
http://www.sw-at.com/blog/2011/03/23/where-does-code-execute-process-address-space-code-gvar-bss-heap-stack/
http://www.sw-at.com/blog/2011/03/23/where-does-code-execute-process-address-space-code-gvar-bss-heap-stack/
Definición del problema 
◦ La memoria local a los subprogramas se gestiona en la pila de 
memoria 
◦ Cada proceso de un programa tiene su propia pila de memoria, por 
lo que en general la pila tiene un tamaño muy limitado 
◦ La memoria dinámica se gestiona en un bloque muy grande de 
memoria (heap/montículo) 
5 
Imagen extraída de: www.sw-at.com 
Stack 
Heap 
Global 
Código 
PROGRAM Memoria; 
VAR 
 precio: real; 
 
FUNCTION CalculoIVA(p: real): real; 
BEGIN 
 CalculoIVA := p*0.21; 
END; 
 
BEGIN 
 precio := 200.25; 
 writeln(‘El IVA es: ’, CalculoIVA(precio)); 
END; 
global 
local 
http://www.sw-at.com/blog/2011/03/23/where-does-code-execute-process-address-space-code-gvar-bss-heap-stack/
http://www.sw-at.com/blog/2011/03/23/where-does-code-execute-process-address-space-code-gvar-bss-heap-stack/
http://www.sw-at.com/blog/2011/03/23/where-does-code-execute-process-address-space-code-gvar-bss-heap-stack/
Definición del problema 
 Para algunos problemas de programación no se conoce en 
tiempo de diseño cuánta memoria necesitaremos ni cómo 
se va a organizar 
 
 Solución: definir y organizar esa memoria en tiempo de 
ejecución 
◦ Para ello, se utilizan estructuras de memoria dinámica 
 
 La gestión de memoria dinámica se realiza a través de 
variables capaces de guardar direcciones de memoria: 
punteros 
6 
¿Qué es eso de...? 
 Memoria dinámica: memoria en la que se puede reservar 
espacio en tiempo de ejecución 
◦ El heap es el bloque del espacio direccionable de memoria dedicado 
para la memoria dinámica 
 
 Estructuras de datos dinámicas: colección de elementos 
(denominados nodos) que se crean o destruyen en tiempo 
de ejecución. 
 
 Variables Dinámicas: Posiciones de memoria reservadas en 
tiempo de ejecución 
 
7 
Punteros 
 Una variable puntero se puede declarar como tipo anónimo, o como 
tipo definido por el usuario 
VAR 
 pointer: ^integer; 
Variable puntero de tipo 
anónimo identificada por 
pointer 
TYPE 
 TPointer = ^integer; 
VAR 
 pointer: TPointer; Variable declarada del 
tipo anterior 
Tipo TPointer definido 
por el usuario para crear 
variables puntero a entero 
8 
Punteros 
 Un tipo puntero se puede usar para declarar variables de ese tipo 
◦ Igual que un tipo Entero se usa para declarar variables de tipo entero (que 
guarda valores de ese tipo) 
 
 
 
 
 
 
 
 
 
◦ Una variable puntero almacena una dirección de memoria donde guardar un 
valor del “tipo base” del puntero (releer hasta estar bien seguro de 
entenderlo) 
TYPE 
 TPrecio = integer; 
VAR 
 precioPan: TPrecio; 
BEGIN 
 precioPan := 85; 
 writeln(precioPan); 
END. 
9 
TYPE 
 TPunteroEntero = ^integer; 
VAR 
 pEntero: TPunteroEntero; 
Punteros 
 Simulación en memoria 
 
85 
??? 
pEntero 
precioPan 
Dirección $3$12 
identificada 
como 
precioPan 
Valor (85) que 
guarda 
precioPan 
10 
TYPE 
 TPrecio = integer; 
 TPunteroEntero = ^integer; 
VAR 
 precioPan: TPrecio; 
 pEntero: TPunteroEntero; 
BEGIN 
 precioPan := 85; 
 writeln(precioPan); 
END. 
Operaciones con punteros 
 Operador @ (Referencia) 
◦ Obtención de la dirección de memoria de una variable 
 
 
 
 
 
 Operador ^ (Desreferencia) 
◦ Acceso al valor de la variable apuntada desde el puntero 
VAR 
 pEntero: ^integer; 
 precioPan: integer; 
BEGIN 
 precioPan := 85; 
 pEntero := @precioPan; 
 ... 
 ... 
 pEntero^ := 100; 
 writeln(precioPan); {imprime 100} 
pEntero^ y 
precioPan son 
sinónimos 
11 
Punteros 
 Simulación en memoria 
 
85 
$3$12 
Valor (85) que 
guarda 
precioPan 
Si pEntero contiene el valor $3$12, y esa es la dirección de memoria de 
la variable precioPan, se dice que pEntero apunta a precioPan 
pEntero 
precioPan 
12 
Dirección $3$12 
identificada 
como 
precioPan 
TYPE 
 TPrecio = integer; 
 TPunteroEntero = ^integer; 
VAR 
 precioPan: TPrecio; 
 pEntero: TPunteroEntero; 
BEGIN 
 precioPan := 85; 
 pEntero := @precioPan; 
 writeln(precioPan); 
END. 
Punteros 
 Simulación en memoria 
 
85 
$3$12 
Valor (85) que 
guarda 
precioPan 
Si pEntero contiene el valor $3$12, y esa es la dirección de memoria de 
la variable precioPan, se dice que pEntero apunta a precioPan 
pEntero 
precioPan 
13 
Dirección $3$12 
identificada 
como 
precioPan 
TYPE 
 TPrecio = integer; 
 TPunteroEntero = ^integer; 
VAR 
 precioPan: TPrecio; 
 pEntero: TPunteroEntero; 
BEGIN 
 precioPan := 85; 
 pEntero := @precioPan; 
 pEntero^ := 100; 
 writeln(precioPan); 
END. Desde pEntero se 
altera el valor de 
precioPan (100) 
100 
Operador @: Ejemplo (1/3) 
Reservamos en tiempo de 
compilación un bloque de memoria 
para un registro y otro para un 
puntero (ESTÁTICOS!!) 
registro 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro= ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 registro: tRegistro; 
BEGIN 
 ... 
 registro.iniciales:=‘ASM’; 
 registro.identificacion:=23455; 
 ... 
 pRegistro := @ registro; 
 ... 
END. 
pRegistro 
14 
Operador @: Ejemplo (2/3) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro= ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 registro: tRegistro; 
BEGIN 
 ... 
 registro.iniciales:=‘ASM’; 
 registro.identificacion:=23455; 
 ... 
 pRegistro := @ registro; 
 ... 
END. 
Inicializamos el registro de la manera 
habitual 
Char[3] 'A' 
'S' 'M' 
23455 
pRegistro 
registro 
15 
Operador @: Ejemplo (y 3/3) 
Apuntamos con el puntero el bloque 
de memoria del registro. Tenemos 
accesible la información del registro 
a través del puntero. 
Char[3] 'A' 
'S' 'M' 
23455 
registro 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro= ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 registro: tRegistro; 
BEGIN 
 ... 
 registro.iniciales:=‘ASM’; 
 registro.identificacion:=23455; 
 ... 
 pRegistro := @registro; 
 ... 
END. 
pRegistro 
16 
Operador ^: Ejemplo (1/3) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro= ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 reg: tRegistro; 
BEGIN 
 ... 
 pRegistro:=@reg; 
 … 
 pRegistro^.iniciales:=‘JJP’; 
 pRegistro^.identificacion:=23456; 
 ... 
END. 
reg 
Reservamos en tiempo de 
compilación un bloque de memoria 
para un registro y otro para un 
puntero (ESTÁTICOS!!) 
pRegistro 
17 
Operador ^: Ejemplo (2/3) 
Apuntamos con el puntero el bloque 
de memoria del registro.
reg 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro= ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 reg: tRegistro; 
BEGIN 
 ... 
 pRegistro:=@reg; 
 … 
 pRegistro^.iniciales:=‘JJP’; 
 pRegistro^.identificacion:=23456; 
 ... 
END. 
pRegistro 
18 
Operador ^: Ejemplo (y 3/3) 
Accedemos al campo “iniciales” e 
“identificacion”del dato de tipo 
tRegistro y asignamos valores 
(NO asignamos valores al puntero, 
sino al dato al que apunta) 
Char[3] 'J' 
'J' 'P' 
23456 
reg 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro= ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 reg: tRegistro; 
BEGIN 
 ... 
 pRegistro:=@reg; 
 … 
 pRegistro^.iniciales:=‘JJP’; 
 pRegistro^.identificacion:=23456; 
 ... 
END. 
pRegistro 
19 
Operaciones con Punteros 
 Operaciones permitidas: 
◦ Asignación (:=) 
◦ Comparación (= y <>) 
 
 
 Para realizar estas operaciones los operandos han de ser 
punteros a variables del mismo tipo o NIL. 
 
 
 Los punteros no se pueden leer ni escribir directamente. 
 
20 
Operaciones: ejemplos (1) 
TYPE 
 ptrACaracter = ^char; 
VAR 
 p1,p2: ptrACaracter; 
 c1,c2: char; 
BEGIN 
 c1:='a'; 
 c2:='h'; 
 p1:=@c1; 
 p2:=@c2; 
 ... 
END. 
'a' 
'h' 
c1 
c2 
p1 
p2 
En esta situación: 
p1 = p2 --> FALSE 
p1 <> p2 --> TRUE 
p1^ = p2^ --> FALSE 
21 
Operaciones: ejemplos (2) 
TYPE 
 ptrACaracter = ^char; 
VAR 
 p1,p2: ptrACaracter; 
 c1,c2: char; 
BEGIN 
 c1:='a'; 
 c2:='h'; 
 p1:=@c1; 
 p2:=@c2; 
 p1:=p2; 
 ... 
END. 
'a' 
'h' 
c1 
c2 
p1 
p2 
Asignación de punteros. 
En esta situación: 
p1 = p2 --> TRUE 
p1 <> p2 --> FALSE 
p1^ = p2^ --> TRUE 
22 
Operaciones: ejemplos (3) 
TYPE 
 ptrACaracter = ^char; 
VAR 
 p1,p2: ptrACaracter; 
 c1,c2: char; 
BEGIN 
 c1:='a'; 
 c2:='h'; 
 p1:=@c1; 
 p2:=@c2; 
 p1^:=p2^; 
 ... 
END. 
'h' 
'h' 
c1 
c2 
p1 
p2 
Asignación de valores 
En esta situación: 
p1 = p2 --> FALSE 
p1 <> p2 --> TRUE 
p1^ = p2^ --> TRUE 
23 
Procedimientos y funciones 
 Pueden ser parámetros, por valor y por referencia, de los 
subprogramas. 
 Se pueden devolver como resultado de una función. 
 Aunque f sea una función que devuelva un puntero a un registro, no 
se permite: 
 
 La sintaxis correcta es: 
 
y posteriormente sí se puede acceder al campo: 
varPuntero:=f(parámetrosReales); 
varPuntero^.campoDelReg; 
f(parámetrosReales)^.campoDelReg; 
24 
Paso por valor de punteros 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 registro: tRegistro; 
 
PROCEDURE miProc(dato: tPtrRegistro); 
BEGIN 
 ... 
END; 
 
BEGIN 
 registro.iniciales:=‘ASM’; 
 registro.identificacion:=23455; 
 pRegistro := @ registro; 
 miProc(pRegistro); 
 ... 
END. 
El procedimiento recoge una copia 
del puntero, que apunta al mismo 
lugar que el original. 
Cualquier cambio en esa información 
se verá reflejada en la información 
apuntada por el puntero original. 
25 
Paso por valor de punteros 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
VAR 
 pRegistro: tPtrRegistro; 
 registro: tRegistro; 
 
PROCEDURE miProc(dato: tPtrRegistro); 
BEGIN 
 ... 
END; 
 
BEGIN 
 registro.iniciales:=‘ASM’; 
 registro.identificacion:=23455; 
 pRegistro := @ registro; 
 miProc(pRegistro); 
 ... 
END. 
Char[3] 'A' 
'S' 'M' 
23455 
pRegistro 
registro 
dato 
Cualquier cambio en esa información 
se verá reflejada en la información 
apuntada por el puntero original. 
26 
Operación new 
new: procedimiento por el que se reserva un espacio de memoria 
dinámica 
 No siempre es obligatorio reservar memoria para utilizar un puntero 
(ver ejemplos anteriores) 
 Sintaxis: 
 
 Semántica: 
◦ reserva espacio de memoria para almacenar un dato del tipo base 
◦ y la variable puntero que se pasa como parámetro se deja apuntando a dicho 
espacio 
 
new(variablePuntero); 
27 
new: ejemplo (1/2) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... 
END. 
Declaramos la variable estática (se 
reserva memoria en tiempo de 
compilación) puntero pRegistro 
pRegistro 
28 
new: ejemplo (2/2) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... 
END. 
new reserva memoria (para guardar 
un registro de tipo tRegistro) en 
tiempo de ejecución (dinámica) y el 
puntero que le pasamos 
(pRegistro) se deja apuntando a 
esa porción reservada . 
pRegistro 
29 
Operación dispose 
dispose: procedimiento por el que se libera memoria dinámica 
 Sintaxis: 
 
 Semántica: 
◦ Libera el espacio de memoria apuntado por la variable puntero que se pasa 
como parámetro 
dispose(variablePuntero); 
30 
dispose: ejemplo (1/3) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 dispose(pRegistro); 
 ... 
END. 
Declaramos la variable estática (se 
reserva memoria en tiempo de 
compilación) puntero pRegistro 
pRegistro 
31 
dispose: ejemplo (2/3) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 dispose(pRegistro); 
 ... 
END. 
pRegistro 
new reserva memoria (para guardar 
un registro de tipo tRegistro) en 
tiempo de ejecución (dinámica) y el 
puntero que le pasamos 
(pRegistro) se deja apuntando a 
esa porción reservada . 
32 
dispose: ejemplo (3/3) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 dispose(pRegistro); 
 ... 
END. 
pRegistro 
dispose libera la memoria 
apuntada por el puntero. 
33 
Nino
Resaltado
Desreserva el puntero apuntado, no borra ni modifica los datos que habían. 
Apuntar a NIL el puntero para que así no apunte a nada
Nino
Resaltado
Puntero nulo: NIL 
 NIL (Puntero nulo) es una constante de tipo puntero 
 Un puntero NIL, indica que no apunta a ninguna posición 
de memoria 
 
34 
NIL: ejemplo (1/4) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 dispose(pRegistro); 
 pRegistro := NIL; 
 ... 
END. 
Declaramos la variable estática (se 
reserva memoria en tiempo de 
compilación) puntero pRegistro 
pRegistro 
35 
NIL: ejemplo (2/4) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 dispose(pRegistro);
pRegistro := NIL; 
 ... 
END. 
pRegistro 
new reserva memoria (para guardar 
un registro de tipo tRegistro) en 
tiempo de ejecución (dinámica) y el 
puntero que le pasamos 
(pRegistro) se deja apuntando a 
esa porción reservada . 
36 
NIL: ejemplo (3/4) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 dispose(pRegistro); 
 pRegistro := NIL; 
 ... 
END. 
pRegistro 
dispose libera la memoria 
apuntada por el puntero. 
37 
NIL: ejemplo (4/4) 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 dispose(pRegistro); 
 pRegistro := NIL; 
 ... 
END. 
pRegistro 
asignar NIL al puntero, indica que no 
apunta a ninguna dirección de 
memoria. 
38 
Efecto de omitir el dispose 
TYPE 
 tIniciales = string[3]; 
 tRegistro = RECORD 
 iniciales: tIniciales; 
 identificacion: Integer; 
 END; 
 tPtrRegistro = ^tRegistro; 
 
VAR 
 pRegistro: tPtrRegistro; 
 
BEGIN 
 ... 
 new(pRegistro); 
 ... {Utilización de pRegistro} ... 
 pRegistro := NIL; 
 ... 
END. 
pRegistro 
Si, en el código anterior, se omite la 
liberación de memoria (mediante 
dispose), el resultado es que se 
mantiene reservada una porción de 
memoria innaccesible, ya que se ha 
desapuntado con la asignación de 
NIL a pRegistro. 
39 
Resumen y conclusiones 
 variablePuntero ≠ variablePuntero^ 
 Es muy conveniente liberar el espacio de memoria dinámica mediante 
dispose cuando no se vaya a utilizar más 
 Declarar una variable de tipo puntero no siempre es suficiente para 
poder utilizarla 
 Para crear información dinámicamente se debe llamar al 
procedimiento new. 
 Después de llamar a new, el valor al que apunta el puntero es 
indefinido. Para definirlo es necesario asignarle un valor. 
 Se verán usos más interesantes de los punteros a lo largo de esta 
asignatura 
40 
Estructura de Datos/Temario/Tema1_IntroduccionTAD_new.pdf
TEMA 1 
Introducción a los 
TADs 
ESTRUCTURAS DE DATOS 
1 
Objetivos 
 Preliminares, eficiencia y corrección 
◦ Análisis de complejidad algorítmica en notación O() 
 Abstracción de datos 
 Presentar los Tipos Abstractos de Datos (TAD’s) 
 Presentar la especificación algebraica de TAD’s 
 
2 
Contenidos 
 1.1 Preliminares 
◦ Normas de estilo 
◦ Conceptos aprendidos 
◦ Paradigmas y lenguajes de programación 
◦ Eficiencia y corrección 
 1.2 Abstracción de datos y TAD’s 
◦ Diseño basado en abstracciones: abstracción procedimental y de datos 
◦ Definición de TAD’s y realización de TAD’s en Pascal 
◦ Especificación algebraica de TAD’s 
 
3 
1.1 Preliminares 
 ¿Qué debemos saber? 
◦ El lenguaje Pascal 
◦ Entorno EclipseGavab 
◦ https://github.com/codeurjc/eclipse-gavab 
◦ https://bintray.com/sidelab-urjc/EclipseGavab 
◦ Soltura con la sintaxis e instrucciones de control 
◦ Especialmente Arrays, Registros y Punteros 
 Ciclo de Vida del Software 
◦ Análisis: Qué se hace 
◦ Diseño: Cómo se hace 
◦ Codificación: Se hace 
◦ Pruebas: Se prueba y se corrige 
◦ (Mantenimiento: Se corrige y amplía) 
4 
https://github.com/codeurjc/eclipse-gavab
https://github.com/codeurjc/eclipse-gavab
https://github.com/codeurjc/eclipse-gavab
https://github.com/codeurjc/eclipse-gavab
https://bintray.com/sidelab-urjc/EclipseGavab
https://bintray.com/sidelab-urjc/EclipseGavab
https://bintray.com/sidelab-urjc/EclipseGavab
1.1 Preliminares 
 Conceptos aprendidos 
Problema Algoritmo 
Programa 
Atajo tentador 
Fase de implementación 
Fase de resolución 
5 
1.1 Preliminares: normas de estilo 
 Eliminar varias instrucciones en una misma línea 
 Tabular adecuadamente el anidamiento que generen algunas 
sentencias: 
◦ Evitar: 
 
 
 Salvo contadores, identificadores mnemotécnicos que describan 
cometido o lo que representan (subprogramas y variables). 
 Palabras reservadas en mayúsculas 
◦ WHILE, FOR, RECORD,... 
IF precio>MAXIMO THEN writeln(‘Precio abusivo’); 
6 
1.1 Preliminares: normas de estilo 
Identificadores: descriptivos y minúsculas 
◦ Identificadores con varias palabras, unidas por '_', o con el primer 
carácter de la palabra sufija en mayúscula, o ambos 
◦ Ej.: nombre_archivo, nombreArchivo, nombre_Archivo, … 
◦ Constantes en mayúsculas 
◦ Ej.: IVA, PI, NUMERO_E, ... 
◦ Procedimientos: Empezando por letra mayúscula. 
◦ Ej.: BusquedaBinaria, Apilar, PilaVacia, ... 
◦ Tipos: Empezando por “Tipo” o “T” 
◦ Ej.: TipoPila, TPila, ... 
7 
1.1 Preliminares: normas de estilo 
 Módulos y Ficheros: 
◦ Nombres de programas y módulos (unidades) deben coincidir con los 
nombres de los ficheros que los contienen. 
◦ Empezando por mayúsculas y resto minúsculas 
◦ Escribir una cabecera de identificación como la que se muestra a 
continuación: 
{********************************************************************* 
* * 
* Módulo: Nombre * 
* Fichero: ( ) Programa ( ) Espec. TAD ( ) Impl. TAD ( ) Otros * 
* Autor(es): Nombre(s) * 
* Fecha: Fecha de actualización * 
* * 
* Descripción: * 
* Breve descripción del módulo (párrafo corto) * 
* * 
*********************************************************************} 
8 
1.1 Preliminares: normas de estilo 
 Uso extendido de subprogramas para tareas bien 
identificadas 
 Adecuado uso de sentencias de repetición (especialmente 
bucles FOR y WHILE) 
◦ Esquema de búsqueda vs recorrido 
 Evitar variables globales en subprogramas 
 Uso adecuado de funciones 
◦ Devuelven un único valor 
 
9 
1.1 Preliminares: conceptos aprendidos 
 Arrays en Pascal: 
◦ Un tipo de dato array se define en la sección de declaración de tipos 
TYPE 
TYPE 
 TipoCoordenada = ARRAY [1..3] OF real; 
 TipoVector = ARRAY [1..3] OF real; 
 TipoMatriz = ARRAY [1..3, 1..7] OF char; 
 TipoViviendas = ARRAY [1..3, 1..3, ’A’..’E’]OF boolean; 
 
VAR 
 origen: TipoCoordenada; 
 desplazamiento: TipoCoordenada TipoVector; 
 
10 
1.1 Preliminares: conceptos aprendidos 
 Arrays en Pascal (cont.): 
◦ Los arrays son estructuras de acceso directo, ya que permiten 
almacenar y recuperar directamente los datos, especificando su 
posición dentro de la estructura. 
◦ Los arrays son estructuras de datos homogéneas: sus elementos son 
todos del mismo tipo. 
◦ El tamaño de un array se establece de forma fija, en un programa, 
cuando se define una variable de este tipo. 
◦ Cuidado con paso de arrays como parámetros de tipo anónimo a 
subprogramas. 
 
11 
1.1 Preliminares: conceptos aprendidos 
 Registros en Pascal: 
◦ Tipo de datos estructurado que permite almacenar datos 
heterogéneos (de distintos tipos) 
TYPE 
 TNombreReg = RECORD 
 idCampo1 : idTipo1; 
 idCampo2 : idTipo2; 
 ... 
 idCampon : idTipon 
 END; {Fin de TNombreReg} 
12 
1.1 Preliminares: conceptos aprendidos 
Registros en Pascal (cont.): 
◦ Las funciones no pueden devolver un registro. 
◦ Para acceder a un campo se usa el operador punto (.): 
 
 
◦ También se puede acceder a los campos de un registro “abriendo” el 
registro con la sentencia WITH 
◦ Absolutamente no recomendado 
NombreVariableRegistro.NombreCampo 
13 
1.1 Preliminares: conceptos aprendidos 


Continuar navegando