Logo Studenta

Apuntes completos de EDI _Estructura de Datos y de la Información_ en C__

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

EDI todo/ejercs T-1.pdf
 1 
Estructuras de Datos y de la Información 
Ingeniería Técnica en Informática de Gestión. Curso 2007/2008 
Ejercicios del Tema 1 
 
Análisis de algoritmos iterativos 
1. Determina la complejidad temporal en el caso peor y en el caso mejor de los siguientes algorit-
mos de ordenación. 
 (a) Ordenación por inserción 
void ordenaIns ( int v[], int num ) { 
 int i, j, x; 
 
 for ( i = 1; i < num; i++ ) { 
 x = v[i]; 
 j = i-1; 
 while ( (j >= 0 ) && (v[j] > x) ){ 
 v[j+1] = v[j]; 
 j = j-1; 
 } 
 v[j+1] = x; 
 } 
} 
 
 (b) Ordenación por selección 
void ordenaSel ( int v[], int num ) { 
 int i, j, menor, aux; 
 
 for ( i = 0; i < num; i++ ) { 
 menor = i; 
 for ( j = i+1; j < num; j++ ) 
 if ( v[j] < v[menor] ) 
 menor = j; 
 if ( i != menor ) { 
 aux = v[i]; 
 v[i] = v[menor]; 
 v[menor] = aux; 
 } 
 } 
} 
 (c) Método de la burbuja 
void ordenaBur ( int v[], int num ) { 
 int i, j, aux; 
 bool modificado; 
 i = 0; 
 modificado = true; 
 while ( (i < num-1) && modificado ) { 
 modificado = false; 
 for ( j = num-1; j > i; j-- ) 
 if ( v[j] < v[j-1] ) { 
 aux = v[j]; 
 v[j] = v[j-1]; 
 v[j-1] = aux; 
 modificado = true; 
 } 
 i++; 
 } 
} 
 2 
2. Determina la complejidad temporal en el caso peor del siguiente algoritmo. 
int buscaBin( int v[], int num, int x ) { 
 int izq, der, centro; 
 
 izq = -1; 
 der = num; 
 while ( der != izq+1 ) { 
 centro = (izq+der) / 2; 
 if ( v[centro] <= x ) 
 izq = centro; 
 else 
 der = centro; 
 } 
 return izq; 
} 
3. El siguiente algoritmo de búsqueda decide si un entero dado aparece o no dentro de un vector de 
enteros dado: 
bool busca( int v[], int num, int x ) { 
// Pre.: v es un array de al menos num elementos 
 int j; 
 bool encontrado; 
 
 j = 0; 
 encontrado = false; 
 while ( (j < num) && ! encontrado ) { 
 encontrado = ( v[j] == x ); 
 j++; 
 } 
 return encontrado; 
// Post.: devuelve true si x aparece en v entre las posiciones 0 .. num-1 
// y false en caso contrario 
} 
Analiza la complejidad en promedio del algoritmo, bajo las hipótesis siguientes: (a) la probabilidad de 
que x aparezca en v es un valor constante p, 0 < p < 1; y (b) la probabilidad de que x aparezca en 
la posición i de v (y no en posiciones anteriores) es la misma para cada índice i, 0 ≤ i < num. 
4. Las dos implementaciones siguientes calculan la potencia nm: 
int potencia1(int n, int m) 
{ 
 int p; 
 p=1; 
 while (m>0) 
 { 
 p=p*n; m--; 
 } 
 return p; 
} 
int potencia2(int n, int m) 
{ 
 int p; 
 p=1; 
 while (m>0) 
 { 
 if (m%2!=0) p=p*n; 
 m=m/2; 
 n=n*n; 
 } 
 return p; 
} 
Describir su funcionamiento y determinar su complejidad en el peor caso, ¿cuál es mejor?. 
 3 
5. (Febrero 2003) Describir brevemente lo que hace el siguiente fragmento de código y determinar 
su complejidad asintótica en función de n: 
for (i=1; i<=n; i++){ 
 for (j=1; j<=n-i; j++) cout << " "; 
 for (j=1; j<=i; j++) cout << j; 
 for (j=i-1; j>=1; j--) cout << j; 
 cout << "\n"; 
} 
6. Los algoritmos de ordenación de arrays han sido objeto de estudio meticuloso en el área de la in-
formática, así como la complejidad asociada a los mismos. Los que hemos estudiado nosotros 
hasta el momento son generales en el sentido de que, en principio, sirven para ordenar cualquier 
array de enteros (es muy fácil modificarlos para ordenar arrays de cualquier tipo ordenado). 
Sin embargo, para algunos problemas concretos es posible sacar partido de las particularidades 
del problema. Por ejemplo, si sabemos que el array a ordenar v[1..n] contiene enteros en un rango 
acotado (y relativamente pequeño), n0 ≤ v[i] ≤ n1 para todo i ∈ {1, . . . , n}, podemos utilizar el 
siguiente algoritmo: 
 construir la tabla de frecuencias t asociada a v. Esta tabla no es más que un array t[n0..n1] tal 
que t[i] contiene el número de apariciones del elemento i en el array inicial v 
 a partir de la tabla de frecuencias, obtener la ordenación del vector v. La idea es: colocar al 
principio de v t[n0] elementos n0, a continuación colocar t[n0 +1] elementos n1 y así sucesi-
vamente. 
Por ejemplo, consideremos v = [1, 3, 2, 4, 5, 3, 4, 2, 3, 1, 4, 5] 
Todos los elementos están en el rango [1.,5]. La tabla de frecuencias asociada es: 
1 2 3 4 5
t 2 2 3 3 2
Ahora, colocamos en v en este orden 2 unos, 2 doses, 3 treses, 3 cuatros y 2 cincos, y obtenemos 
el array ordenado: 
v = [1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5] 
Implementar este algoritmo en C++ para vectores de enteros en el rango 0.,999. ¿Cuál es la com-
plejidad del algoritmo en el peor caso? ¿Y en el mejor? Ampliar la funcionalidad de modo que el 
rango de los elementos se determine en tiempo de ejecución y el algoritmo opere de acuerdo con 
este dato. ¿Cuál es la complejidad de este nuevo algoritmo? 
7. (Junio 2003) Hoy es día de excursión para todo el cole y los niños están muy contentos. Como 
son muchísimos niños, para evitar despistes y no perder a ninguno, la señorita encargada los ha 
colocado por orden alfabético. Sin embargo, en un despiste de la “seño”, algunos niños han 
hecho de las suyas y han intercambiado su posición con la de uno de los compañeros de al lado 
(el de la izquierda o el de la derecha). Los niños más revoltosos han repetido este proceso varias 
veces, mientras que hay otros que no se han movido ni una sola vez, como Remedios que es muy 
buena. La señorita se enfada mucho cuando descubre el desaguisado: “He malgastado n*log(n) (uni-
dades de tiempo, siendo n el número de niños) en ordenaros... ¡Os pondré un negativo a todos!”. Pero Remedios, 
que tiene un expediente inmaculado, protesta: “Seño, yo no me he movido ninguna vez. Jaimito es el que 
más veces se ha movido. Yo lo he visto... y se ha movido 4 veces”. 
Casualmente un alumno de EDI que ve lo que ha ocurrido y tranquiliza a la señorita diciéndole 
que la entropía generada por los niños no es excesiva y que de hecho puede diseñar un algoritmo 
de complejidad lineal para recomponer la ordenación. Asumiendo que los niños están representa-
dos en un vector diseña e implementa un algoritmo que reconstruya la ordenación en tiempo 
lineal. Por simplicidad, puedes suponer que cada niño está representado por un entero con res-
pecto al que se ordena. Razona que el algoritmo construido es de complejidad lineal. 
 4 
Órdenes de Complejidad 
8. Demostrar: 
a) f(n) ∈ O(g(n)) ⇔ O(f(n)) ⊆ O(g(n)) 
b) O(f(n)) = O(g(n)) ⇔ f(n) ∈ O(g(n)) y g(n) ∈ O(f(n)) 
d) O(c · f(n)) = O(f(n)), siendo c > 0. 
9. Demostrar la regla de la suma para el orden exacto: 
Θ(f(n) + g(n)) = Θ(max(f(n), g(n))) 
10. Demostrar las siguientes inclusiones estrictas: 
O(1) ⊂ O(log(n)) ⊂ O(n) ⊂ O(n ¢ log(n)) ⊂ O(n2) ⊂ O(n3) ⊂ . . . ⊂ O(nk) ⊂ O(2n) ⊂ O(n!) 
11. Demostrar la propiedad de la dualidad: 
f(n) ∈ O(g(n)) ⇔ g(n) ∈ Ω(f(n)) 
12. Demostrar o refutar las siguientes propiedades: 
a) f(n) ∈ O(n2) y g(n) ∈ O(n) ⇒ f(n)/g(n) ∈ O(n) 
b) f(n) ∈ Θ (n2) y g(n) ∈ Θ (n) ⇒ f(n)/g(n) ∈ Θ (n) 
13. Demostrar o refutar las siguientes afirmaciones: 
a) 2n + n99 ∈ O(n99) 
b) 2n + n99 ∈ Ω(n99) 
c) 2n + n99 ∈ Θ(n99) 
d) 2n + n99 ∈ O(2n) 
e) 2n + n99 ∈ Ω(2n) 
f) 2n + n99 ∈ Θ(2n) 
14. Buscar ejemplos de funciones f(n) y g(n) tales que f(n) ∈ O(g(n)) pero f(n) ∉ Ω(g(n)) 
EDI todo/ejercs T-2.pdf
 1 
Estructuras de Datos y de la Información 
Ingeniería Técnica en Informática de Gestión. Curso 2007/2008 
Ejercicios del Tema 2 
Diseño de algoritmos recursivos 
1. Dado un vector de enteros de longitud N, diseñar un algoritmo de complejidad O(N·logN) que 
encuentre el par de enteros más cercanos. ¿Se puede hacer con complejidad O(N)? 
2. Dado un vector de enteros de longitud N, diseñar un algoritmo de complejidad O(N·logN) que 
encuentre el par de enteros más lejanos. ¿Se puede hacer con complejidad O(N)? 
3. Diseñar un algoritmo recursivo que realice
el cambio de base de un número binario dado en su 
correspondiente decimal. 
4. Diseñar un algoritmo recursivo que, dado un array de caracteres, cuente el número de vocales que 
aparecen en él. 
5. Escribir una función recursiva que devuelva el producto de los elementos de un array mayores o 
iguales que un determinado número b 
6. Implementa una función recursiva simple cuadrado que calcule el cuadrado de un número natural 
n, basándote en el siguiente análisis de casos: 
Caso directo: Si n = 0, entonces n2 = 0 
Caso recursivo: Si n > 0, entonces n2 = (n–1)2 + 2*(n–1) + 1 
7. Implementa una función recursiva log que calcule la parte entera de logb n, siendo los datos b y n 
enteros tales que b ≥ 2 ∧ n ≥ 1. El algoritmo obtenido deberá usar solamente las operaciones de 
suma y división entera. 
8. Implementa una función recursiva bin tal que, dado un número natural n, bin(n) sea otro número 
natural cuya representación decimal tenga los mismos dígitos que la representación binaria de n. 
Es decir, debe tenerse: bin(0) = 0; bin(1) = 1; bin(2) = 10; bin(3) = 11; bin(4) = 100; etc. 
9. Implementa una función recursiva doble que satisfaga la siguiente especificación: 
int sumaVec( int v[], int a, int b ) { 
// Pre: 0 <= a <= num && -1 <= b <= num-1 && a <= b+1 
// siendo num el número de elementos de v 
 
// Post: devuelve la suma de las componentes de v entre a y b 
} 
Básate en el siguiente análisis de casos: 
Caso directo: a ≥ b 
v[a..b] tiene a lo sumo un elemento. El cálculo de s es simple. 
Caso recursivo: a < b 
v[a..b] tiene al menos dos elementos. Hacemos llamadas recursivas para sumar v[a..m] y 
v[m+1..b], siendo m = (a+b) / 2. 
 2 
10. Implementa un procedimiento recursivo simple dosFib que satisfaga la siguiente especificación 
pre/post: 
void dosFib( int n, int& r, int& s ) { 
// Pre: n >= 0 
// Post: r = fib(n) && s = fib(n+1) 
} 
En la postcondición, fib(n) y fib(n+1) representan los números que ocupan los lugares n y n+1 
en la sucesión de Fibonacci, para la cual suponemos la definición recursiva habitual. 
11. Implementa una función recursiva que calcule el número combinatorio ⎟⎟
⎠
⎞
⎜⎜
⎝
⎛
m
n
 a partir de los datos 
m, n: Integer tales que n ≥ 0 ∧ m ≥ 0. Usa la recurrencia siguiente: 
⎟⎟
⎠
⎞
⎜⎜
⎝
⎛ −
+⎟⎟
⎠
⎞
⎜⎜
⎝
⎛
−
−
=⎟⎟
⎠
⎞
⎜⎜
⎝
⎛
m
n
m
n
m
n 1
1
1
 siendo 0 < m < n 
12. Una palabra se llama palíndroma si la sucesión de sus letras no varía al invertir el orden. Especifica 
e implementa una función recursiva final que decida si una palabra dada, representada como vec-
tor de caracteres, es o no palíndroma. 
13. El problema de las torres de Hanoi consiste en trasladar una torre de n discos de diferentes tama-
ños desde la varilla ini a la varilla fin, con ayuda de la varilla aux. Inicialmente los n discos están 
apilados de mayor a menor, con el más grande en la base. En ningún momento se permite que un 
disco repose sobre otro menor que él. Los movimientos permitidos consisten en desplazar el dis-
co situado en la cima de una de las varillas a la cima de otra, respetando la condición anterior. 
Construye un procedimiento recursivo hanoi tal que la llamada hanoi(n, ini, fin, aux) produzca el 
efecto de escribir una serie de movimientos que represente una solución del problema de Hanoi. 
Supón disponible un procedimiento movimiento(i, j), cuyo efecto es escribir "Movimiento de la va-
rilla i a la varilla j ". 
Análisis de algoritmos recursivos 
14. En cada uno de los casos que siguen, plantea una ley de recurrencia para la función T(n) que mide 
el tiempo de ejecución del algoritmo en el caso peor, y usa el método de desplegado para resolver 
la recurrencia. 
 (a) Función log (ejercicio 2). 
 (b) Función bin (ejercicio 3). 
 (c) Función sumaVec (ejercicio 4). 
 (d) Procedimiento dosFib (ejercicio 5). 
 (e) La función del ejercicio 6. 
 (f) Función palindroma (ejercicio 7). 
 (g) Procedimiento hanoi (ejercicio 8). 
15. Aplica las reglas de análisis para dos tipos comunes de recurrencia a los algoritmos recursivos del 
ejercicio anterior. En cada caso, deberás determinar si el tamaño de los datos del problema decre-
ce por sustracción o por división, así como los parámetros relevantes para el análisis. 
 3 
16. En cada caso, calcula a partir de las recurrencias el orden de magnitud de T(n). Hazlo aplicando 
las reglas de análisis para dos tipos comunes de recurrencia. 
 (a) T(1) = c1; T(n) = 4 ⋅ T(n/2) + n, si n > 1 
 (b) T(1) = c1; T(n) = 4 ⋅ T(n/2) + n2, si n > 1 
 (c) T(1) = c1; T(n) = 4 ⋅ T(n/2) + n3, si n > 1 
17. Usa el método de desplegado para estimar el orden de magnitud de T(n), suponiendo que T obe-
dezca la siguiente recurrencia: 
 T(1) = 1; T(n) = 2 ⋅ T(n/2) + n ⋅ log n, si n > 1 
¿Pueden aplicarse en este caso las reglas de análisis para dos tipos comunes de recurrencia? 
¿Por qué? 
Eliminación de la recursión final 
18. Aplica la transformación de recursivo final a iterativo sobre la función palindroma del ejercicio 7. 
19. La primera versión (la que aparece a la izquierda) de la búsqueda binaria es la misma que aparecía 
en el ejercicio 6 de la hoja 1 de ejercicios, mientras que la segunda (la que aparece a la derecha), 
vista en teoría, es el resultado de transformar a iterativo la versión recursiva de este algoritmo. 
¿En qué se diferencian estos dos algoritmos iterativos? 
Escribe un algoritmo recursivo final con la misma idea de la primera versión iterativa. 
 
int buscaBin( TElem v[], int num, TElem x ) 
{ 
 int izq, der, centro; 
 
 izq = -1; 
 der = num; 
 while ( der != izq+1 ) { 
 centro = (izq+der) / 2; 
 if ( v[centro] <= x ) 
 izq = centro; 
 else 
 der = centro; 
 } 
 return izq; 
} 
 
int buscaBin( TElem v[], int num, TElem x ) 
{ 
 int a, b, p, m; 
 
 a = 0; 
 b = num-1; 
 while ( a <= b ) { 
 m = (a+b) / 2; 
 if ( v[m] <= x ) 
 a = m+1; 
 else 
 b = m-1; 
 } 
 p = a - 1; 
 return p; 
} 
 
 4 
Técnicas de generalización 
20. Se trata de obtener un algoritmo recursivo de complejidad lineal que dado un polinomio de coefi-
cientes enteros, representado como un vector, y el valor de la incógnita, calcule el valor del 
polinomio. En el vector, de tipo int v[ ], se almacenan los coeficientes del polinomio ordenados 
por exponentes: en la posición 0 el coeficiente de x0, en la posición 1 el coeficiente de x, y así su-
cesivamente. 
Idea: Implementa primero una función recursiva evaluaGen de complejidad cuadrática donde las 
potencias de x se obtengan de forma iterativa. A continuación, plantea otra generalización eva-
luaEfi que permita obtener el algoritmo de complejidad lineal, y escribe su implementación 
transformando el código de evaluaGen. Puede conseguirse recursión final. 
21. Comprueba que el procedimiento combiGen especificado como sigue es una generalización de la 
función combi del ejercicio 6, y que combiGen admite un algoritmo recursivo simple, más eficiente 
que la recursión doble de combi, implementándola. 
 
void combiGen ( int a, int b, int v[], int num ) { 
// Pre: 0 <= b <= a && b < num 
// Post: para cada i entre 0 y b se tiene v[i] = ⎟⎟
⎠
⎞
⎜⎜
⎝
⎛
i
a
} 
 
22. Especifica e implementa un algoritmo recursivo que dado un vector de enteros calcule el número 
de posiciones de dicho vector que cumplan la condición de que la suma de las componentes a su 
izquierda coincida con la suma de las componentes a su derecha. Utilizando el método de des-
pliegue de recurrencias, analiza la complejidad temporal en el caso peor del algoritmo obtenido. 
23. Especifica e implementa un algoritmo recursivo que dado un vector de enteros lo reorganice de 
forma que los valores pares ocupen la parte izquierda del vector y los valores impares la parte de-
recha. Utilizando el método de despliegue de recurrencias, analiza la complejidad temporal en el 
caso peor del algoritmo obtenido. 
24. Especifica e implementa un algoritmo recursivo que
dado un vector de enteros determine si el 
vector tiene forma de montaña. Un vector tiene forma de montaña si contiene una secuencia estric-
tamente creciente seguida de una secuencia estrictamente decreciente −una de las dos secuencias 
puede ser vacía–. Utilizando el método de despliegue de recurrencias, analiza la complejidad tem-
poral en el caso peor del algoritmo obtenido. 
25. Especifica e implementa un algoritmo recursivo que dado un vector v de enteros, que viene dado 
en orden estrictamente creciente, determine si el vector contiene alguna posición i que cumpla 
v[i]=i. Utilizando el método de despliegue de recurrencias, analiza la complejidad temporal en el 
caso peor del algoritmo obtenido. 
26. Especifica e implementa un algoritmo recursivo que dados dos vectores u, v de enteros, ordena-
dos en orden estrictamente creciente, obtenga el número de elementos que aparecen en los dos 
vectores. Utilizando el método de despliegue de recurrencias, analiza la complejidad temporal en 
el caso peor del algoritmo obtenido. 
 5 
27. Especifica e implementa un algoritmo recursivo que dado un vector v de enteros determine si 
contiene un punto de inflexión. Un punto de inflexión es una posición del vector tal que todas las 
componentes que aparecen a su izquierda son negativas, y todas las que aparecen a su derecha 
son positivas o 0. Si el vector contiene punto de inflexión la función devolverá su posición, y si 
no lo contiene devolverá –1. Utilizando el método de despliegue de recurrencias, analiza la com-
plejidad temporal en el caso peor del algoritmo obtenido. 
28. Especifica e implementa un algoritmo recursivo que dado un vector v de enteros determine si el 
vector tiene la forma 1n 0n 0n 1n, es decir: un cierto número n de unos, seguidos del doble (2n) de 
ceros, seguidos a su vez de otros n unos. Por ejemplo, un vector de tamaño 8 con las componen-
tes [1,1,0,0,0,0,1,1] cumpliría lo anterior. Utilizando el método de despliegue de recurrencias, 
analiza la complejidad temporal en el caso peor del algoritmo obtenido. 
29. Especifica e implementa un algoritmo recursivo que dado un vector v de enteros determine si el 
vector representa una escalera con peldaños de ancho estrictamente creciente, donde: 
— Un peldaño queda constituido por una secuencia de apariciones consecutivas del mismo ele-
mento. Por ejemplo, el vector [1, 6, 6, 6, 2, 2, 5] tiene 4 peldaños. 
— El ancho de un peldaño es el número de apariciones consecutivas del elemento que constituye 
el peldaño. Por ejemplo, los anchos de los 4 peldaños del vector anterior son 1, 3, 2 y 1 (por 
orden de aparición). 
— Un vector forma una escalera con peldaños de ancho estrictamente creciente si cada peldaño 
es más ancho que el anterior, como, por ejemplo, el vector [3, 3, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5]. 
Utilizando el método de despliegue de recurrencias, analiza la complejidad temporal en el caso 
peor del algoritmo obtenido. 
30. Especifica e implementa un algoritmo recursivo que dado un vector u de enteros obtenga la lon-
gitud de la meseta más larga. Una meseta es un conjunto de posiciones consecutivas del vector que 
contienen el mismo valor. Utilizando el método de despliegue de recurrencias, analiza la comple-
jidad temporal en el caso peor del algoritmo obtenido. 
 
 
 
EDI todo/ejercs T-3.pdf
Estructuras de Datos y de la Información 
Ingeniería Técnica en Informática de Gestión. Curso 2007/2008 
Ejercicios del Tema 3 
Las implementaciones de los TAD se realizarán como clases de C++. En cada caso, se formulará el in-
variante de la representación y las especificaciones pre/post de los procedimientos y funciones que 
realicen las operaciones del TAD. En el caso de los TADs genéricos, la implementación se realizará 
mediante clases parametrizadas (templates o plantillas). 
 
1. Desarrolla un TAD TComplejo que ofrezca el tipo TComplejo junto con las operaciones adecuadas 
para construir números complejos y calcular con ellos. 
2. Desarrolla un TAD TMonomio para representar los monomios como coeficiente y grado, con las 
operaciones de creación, consultar el grado y consultar el coeficiente. 
A continuación, utilizando el TAD TMonomio desarrolla un TAD TPolinomio que ofrezca el tipo de 
los polinomios, con operaciones para crear el polinomio nulo, añadir un nuevo monomio a un 
polinomio, consultar el coeficiente de un determinado grado, consultar el grado del polinomio, 
sumar polinomios y evaluar un polinomio para un valor dado de la indeterminada. 
P ara el TAD TPolinomio construye dos implementaciones: 
— representando los polinomios mediante un vector de monomios ordenados por el grado; y 
— representando los polinomios mediante una lista enlazada de monomios ordenados por el gra-
do. 
3. ñade a la clase TPilaDinamica<TElem> dos nuevas operaciones: A 
— fondo: devuelve el elemento del fondo de una pila no vacía. 
— inversa: devuelve una nueva pila con los elementos de la pila original apilados en orden inverso. 
4. Las pilas formadas por números naturales del intervalo [0..N–1] (para cierto N ≥ 2 fijado de an-
temano) se pueden representar por medio de números, entendiendo que un número natural P 
cuya representación en base N tenga “1” como dígito de mayor peso representa la pila formada 
por los restantes dígitos de la representación de P en base N (excepto el de mayor peso), siendo 
la cima el dígito de menor peso. Por ejemplo, si N = 10, el número 1073 representa la pila que 
contiene los números 0, 7, 3, con 0 en la base y 3 en la cima. Implementa el TAD TPilaNat con 
esta representación. Comprueba que esta representación permite implementar todas las operacio-
nes de las pilas con coste O(1). 
5. Desarrolla un TAD genérico TDosPilas<TElem> que representa una pareja de pilas que pueden 
anejarse independientemente del modo usual. m 
— Desarrolla una implementación estática de este TAD, representando la pareja de pilas con 
ayuda de un único vector de almacenamiento. Organiza la implementación de modo que las 
dos pilas crezcan en sentidos opuestos, cada una desde uno de los dos extremos del vector. 
— Desarrolla una segunda implementación utilizando la clase TPilaDinamica<TElem>. 
6. Especifica e implementa un TAD genérico TLista<TElem> que represente a las listas de elemen-
tos con las siguientes operaciones: 
— Nuevo: crea una lista vacía. 
— Cons: añade un elemento al principio de la lista. 
— ponDr: añade un elemento al final de la lista. 
— primero: devuelve el primer elemento de la lista. 
— resto: elimina el primer elemento de la lista. 
— ultimo: devuelve el último elemento de la lista. 
— inicio: elimina el último elemento de la lista. 
— concatena: añade al final de una lista los elementos de otra. 
 1 
 2 
— esVacio: determina si la lista está vacía. 
— numElem: devuelve el número de elemento de la lista 
— elemEn: devuelve el elemento que está en una cierta posición de la lista, identificada por su 
número de orden. 
La lista se debe implementar como una lista enlazada. 
7. xplica razonadamente qué mostrará este programa por pantalla. E 
typedef TPilaDinamica< TPilaDinamica<int> > TPilas; 
typedef TPilaDinamica< TPilaDinamica<int>* > TPuntPilas; 
 
 
TPilas pilas ( int max ) { 
 TPilas res; 
 TPilaDinamica<int> pila; 
 
 for ( int i = 0; i < max; i++ ) { 
 pila = TPilaDinamica<int>(); 
 for ( int j = 0; j < i; j++ ) 
 pila.apila(j); 
 res.apila(pila); 
 } 
 
 return res; 
} 
 
 
int suma ( TPilas pilaDePilas ) { 
 TPilaDinamica< int > pila; 
 int res; 
 
 res = 0; 
 while ( ! pilaDePilas.esVacio() ) { 
 pila = pilaDePilas.cima(); 
 pilaDePilas.desapila(); 
 while ( ! pila.esVacio() ) { 
 res += pila.cima(); 
 pila.desapila(); 
 } 
 } 
 
 return res; 
} 
 
TPuntPilas pilas2 ( int max ) { 
 TPuntPilas res; 
 TPilaDinamica<int>* pila; 
 
 for ( int i = 0; i < max; i++ ) { 
 pila = new TPilaDinamica<int>(); 
 for ( int j = 0; j < i; j++ ) 
 pila->apila(j); 
 res.apila(pila);
} 
 
 return res; 
} 
 
 
int suma2 ( TPuntPilas pilaDePilas ) 
{ 
 TPilaDinamica< int >* pila; 
 int res; 
 
 res = 0; 
 while ( ! pilaDePilas.esVacio() ) { 
 pila = pilaDePilas.cima(); 
 pilaDePilas.desapila(); 
 while ( ! pila->esVacio() ) { 
 res += pila->cima(); 
 pila->desapila(); 
 } 
 } 
 
 return res; 
} 
 
 
 
int main(int argc, char* argv[]) 
{ 
 TPilas pilaDePilas; 
 TPuntPilas pilaDePilas2; 
 
 pilaDePilas = pilas( 4 ); 
 cout << suma( pilaDePilas ) + suma( pilaDePilas ) << endl; 
 
 pilaDePilas2 = pilas2( 4 ); 
 cout << suma2( pilaDePilas2 ) + suma2( pilaDePilas2 ) << endl; 
} 
		Estructuras de Datos y de la InformaciónIngeniería Técnica en Informática de Gestión. Curso 2007/2008Ejercicios del Tema 3
EDI todo/ejercs T-4.pdf
 1 
Estructuras de Datos y de la Información 
Ingeniería Técnica en Informática de Gestión. Curso 2007/2008 
Ejercicios del Tema 4 
1. Transforma a iterativo los siguiente algoritmos recursivos: 
 (a) Función log del ejercicio 2 de la hoja 2. 
 (b) Procedimiento dosFib del ejercicio 5 de la hoja 2. 
 (c) Función del ejercicio 17 de la hoja 2. 
Aplica en cada caso la técnica de transformación que conlleve un menor consumo de espacio en 
el algoritmo iterativo. 
2. Una frase se llama palíndroma si la sucesión de caracteres obtenida al recorrerla de izquierda a de-
recha (ignorando los blancos) es la misma que si el recorrido se hace de derecha a izquierda. Esto 
sucede, por ejemplo, con la socorrida frase “dábale arroz a la zorra el abad”. Construye una fun-
ción iterativa ejecutable en tiempo lineal, que decida si una frase dada en forma de cola de caracteres 
es o no palíndroma. El algoritmo utilizará una pila de caracteres, declarada localmente. 
3. El agente 0069 ha inventado un nuevo método de codificación de mensajes secretos. El mensaje 
original X se codifica en dos etapas: 
— Primero, X se transforma en X’ reemplazando cada sucesión de caracteres consecutivos que 
no sean vocales por su imagen especular. 
— A continuación, X’ se transforma en la sucesión de caracteres X’’ obtenida al ir tomando suce-
sivamente: el primer carácter de X’; luego el último; luego el segundo; luego el penúltimo; etc. 
Ejemplo: para X = “Bond, James Bond”, resultan: 
X’ = “BoJ ,dnameB sodn” y X’’ = “BnodJo s, dBneam” 
Construye los algoritmos de codificación y descodificación de mensajes y analiza su complejidad, 
utilizando pilas y colas. Supón que el mensaje inicial viene dado como una cola de caracteres. 
4. Añade las siguientes operaciones a la clase TListaDinamica<TElem>: 
— ==: comparación sobre igualdad entre listas 
— <=: comparación de orden entre listas 
— ordenada: determina si una lista está ordenada 
— insertaOrd: inserta un elemento delante del primero que es mayor que él. 
5. Resuelve los problemas que siguen aplicando el esquema de recorrido de secuencias. En cada ca-
so, el contenido de la secuencia debe quedar inalterado. 
 (a) Contar el número de apariciones de ‘a’ en una secuencia de caracteres dada. 
 (b) Dada una secuencia de enteros, contar cuántas posiciones hay en ella tales que el entero que 
aparece en esa posición es igual a la suma de todos los precedentes. 
6. Resuelve los problemas que siguen aplicando el esquema de búsqueda secuencial. 
 (a) Buscar la primera aparición de ‘b’ en una secuencia de caracteres dada. 
 (b) Dada una secuencia de enteros, buscar la primera posición ocupada por un número que sea 
menor que todos los anteriores. 
7. Algunos problemas de procesamiento de secuencias requieren modificar y/o combinar los es-
quemas de recorrido y búsqueda secuencial. Resuelve los casos siguientes: 
 (a) Dada una secuencia de caracteres, copiarla en otra eliminando los blancos múltiples. 
 (b) Contar el número de caracteres anteriores y posteriores a la primera aparición de ‘a’ en una 
secuencia de caracteres dada. 
 (c) Contar el número de parejas de vocales consecutivas que aparecen en una secuencia de ca-
racteres dada. 
 2 
8. Una expresión aritmética construida con los operadores binarios ‘+’, ‘–’, ‘*’, ‘/’ y operandos (re-
presentados cada uno por un solo carácter) se dice que está en forma postfija si es o bien un solo 
operando o dos expresiones en forma postfija una tras otra, seguidas inmediatamente de un ope-
rador. Lo que sigue es un ejemplo de una expresión escrita en la notación infija habitual, junto 
con su forma postfija: 
 Forma infija: (A/(B–C))*(D+E)) Forma postfija: ABC–/DE+* 
Diseña un algoritmo iterativo que calcule el valor de una expresión dada en forma postfija por el 
siguiente método: se inicializa una pila vacía de números y se van recorriendo de izquierda a dere-
cha los caracteres de la expresión. Cada vez que se pasa por un operando, se apila su valor. Cada 
vez que se pasa por un operador, se desapilan los dos números más altos de la pila, se componen 
con el operador, y se apila el resultado. Al acabar el proceso, la pila contiene un solo número, que 
es el valor de la expresión. Representa la expresión dada como secuencia de caracteres, y supón 
disponible una función valor que asocie a cada operando su valor numérico. 
9. Dado un número natural N ≥ 2, se llaman números afortunados a los que resultan de ejecutar el si-
guiente proceso: se comienza generando una cola que contiene los números desde 1 hasta N, en 
este orden; se elimina de la cola un número de cada 2 (es decir, los números 1, 3, 5, etc.); de la 
nueva cola, se elimina ahora un número de cada 3; etc. El proceso termina cuando se va a elimi-
nar un número de cada m y el tamaño de la cola es menor que m. Los números que queden en la 
cola en este momento son los afortunados. Diseña un procedimiento que reciba N como pará-
metro y produzca una secuencia formada por los números afortunados resultantes. 
(Indicación: para eliminar de una cola de n números un número de cada m, hay que reiterar n veces 
el siguiente proceso: extraer el primer número de la cola, y añadirlo al final de la misma, salvo si le 
tocaba ser eliminado.) 
10. Añade las siguientes operaciones a la clase TSecuenciaDinamica<TElem>: 
— busca: operación que busca una secuencia s’ dentro de otra secuencia s. La búsqueda se realiza 
en s, a partir de la posición actual del punto de interés, y los elementos a buscar son aquellos 
que aparecen a la derecha del punto de interés de s’. Esta operación modifica el punto de inte-
rés de s, colocándolo delante de la primera aparición de la subsecuencia buscada, o al final del 
todo si la subsecuencia no se ha encontrado. La operación no está definida si el punto de inte-
rés de s’ está a la derecha del todo –no hay nada que buscar–. 
Por ejemplo, si trabajásemos con secuencias de caracteres: 
 
— borraSec: operación que borra todas las apariciones de una secuencia s’ dentro de otra secuencia 
s. La búsqueda de los elementos a eliminar se realiza de la misma forma que en la operación 
busca, es decir, se busca en s a partir de la posición del punto de interés, y la subsecuencia a 
eliminar es la compuesta por los elementos de s’ a la derecha del punto de interés. Igualmente, 
la operación no está definida si el punto de interés de s’ se encuentra al final. 
11. Implementa el TAD secuencia utilizando como tipo representante una par de listas, según las in-
dicaciones vistas en clase. Para mejorar la eficiencia de algunas operaciones, añade a la 
implementación de las listas una operación de concatenación por la izquierda. 
s : Una casa al borde del mar, un gran mar, en la playa
s’ : La mar
s : Una casa al borde del mar, un gran mar, en la playa
s’ : La mar
Entrada:
Salida:
EDI todo/ejercs T-5.pdf
 1 
Estructuras de Datos y de la Información 
Ingeniería Técnica en Informática de Sistemas. Curso 2007/2008 
Ejercicios del tema 5 
 
Arboles 
1. Añade las siguientes operaciones a la clase TArbinDinamico<TElem>, analizando su complejidad. 
– talla: Arbin[Elem] → Nat 
Calcula la talla de un árbol binario, definida
como el número de nodos de la rama más 
larga. 
– numNodos: Arbin[Elem] → Nat 
Calcula el número de nodos de un árbol binario. 
– numHojas: Arbin[Elem] → Nat 
Calcula el número de hojas de un árbol binario. 
– espejo: Arbin[Elem] → Arbin[Elem] 
Construye la imagen especular de un árbol binario. 
– frontera: Arbin[Elem] → Sec[Elem] 
Obtiene la secuencia formada por los elementos almacenados en las hojas de un árbol 
binario, tomados de izquierda a derecha. 
– ==: (Arbin[Elem], Arbin[Elem]) → Bool 
Determina si dos árboles binarios son iguales. 
2. Un árbol de codificación es un árbol binario a que almacena en cada una de sus hojas un carácter di-
ferente. La información almacenada en los nodos internos se considera irrelevante. Si un cierto 
carácter c se encuentra almacenado en la hoja de posición α, se considera que α es el código asig-
nado a c por el árbol de codificación a. Más en general, el código de cualquier cadena de 
caracteres dada se puede construir concatenando los códigos de los caracteres que la forman, res-
petando su orden de aparición. 
 (a) Dibuja el árbol de codificación correspondiente al código siguiente: 
 
Carácter Código 
‘A’ 1.1 
‘T’ 1.2 
‘G’ 2.1.1 
‘R’ 2.1.2 
‘E’ 2.2 
 
 (b) Construye el resultado de codificar la cadena de caracteres “RETA” utilizando el código 
representado por el árbol de codificación anterior. 
(c) Descifra 1.2.1.1.2.1.2.1.2.1.1 usando el código que estamos utilizando en estos ejemplos, 
construyendo la cadena de caracteres correspondiente. 
(d) Desarrolla un módulo que implemente la clase TArbCod que representa a los árboles de co-
dificación descritos en el ejercicio anterior, equipada con las siguientes operaciones 
– Nuevo: → ArbCod 
Genera un árbol de codificación vacío. 
 2 
 
– Inserta: (ArbCod, Car, Sec[Nat]) – → ArbCod 
Dado un árbol de codificación, un carácter y un código, representado como una secuen-
cia de [1,2], añade el carácter al árbol en el lugar indicado por la secuencia. La operación 
no está definida si el carácter ya formaba parte del árbol. 
– codifica: (ArbCod, Cadena) – → Sec[Nat] 
Construye el código de una cadena. La operación no está definida si la cadena contiene 
algún carácter que no se encuentra codificado en el árbol. 
– decodifica: (ArbCod, Sec[Nat]) – → Cadena 
Construye una cadena a partir de su código. La operación no está definida si no es posi-
ble decodificar toda la entrada. 
3. Modifica las implementaciones desarrolladas en clase para los árboles de búsqueda, de manera 
que las operaciones busca, inserta y borra sean iterativas en lugar de recursivas. 
4. Añade las siguientes operaciones a la clase TArbus<TClave, TValor>, analizando su complejidad. 
– consultaK: (Arbus[Clave,Valor], Nat) → Clave 
Obtiene la k-ésima clave de un árbol de búsqueda, considerando que en un árbol con n 
elementos k=0 corresponde a la menor clave y k=n–1 a la mayor. 
– recorreRango: (Arbus[Clave,Valor], Clave, Clave) → Sec[Valor] 
Dadas dos claves a y b devuelve una secuencia con los valores asociados a las claves que 
están en el intervalo [a .. b ]. 
 
En los dos siguientes ejercicios debes suponer que la clase TArbus<TClave,TValor> está equipada con la 
operación: 
– recorreClaveValor: Arbus[Clave,Valor] → Sec[Pareja[Clave,Valor]] 
Obtiene una secuencia, ordenada por clave, con todas las parejas de clave, valor almacenadas en 
el árbol de búsqueda. 
5. El problema de las concordancias consiste en lo siguiente: Dado un texto, se trata de contar el nú-
mero de veces que aparece en él cada palabra, y producir un listado ordenado alfabéticamente por 
palabras, donde cada palabra aparece acompañada del número de veces que ha aparecido en el 
texto. Suponemos que el texto a analizar viene dado como secuencia de tipo Sec[string], donde ca-
da elemento de la secuencia es una palabra. Se pide construir un algoritmo que resuelva el 
problema con ayuda de un árbol de búsqueda de tipo Arbus[string, int], y analizar su complejidad. 
El listado pedido se dará como secuencia de parejas, de tipo Sec[Pareja[string, int]]. 
6. Dado un texto organizado por líneas, el problema de las referencias cruzadas pide producir un lista-
do ordenado alfabéticamente por palabras, donde cada palabra del texto vaya acompañada de una 
lista de referencias, que contendrá los números de todas las líneas del texto en las que aparece la pa-
labra en cuestión (con posibles repeticiones si la palabra aparece varias veces en una misma línea). 
Suponiendo que el texto a analizar venga dado como secuencia de tipo Sec[Sec[string]] –secuencia 
de líneas representadas como secuencias de palabras–, construye un algoritmo que resuelve el 
problema con ayuda de un árbol de búsqueda de tipo Arbus[string, Sec[int]], y analiza su compleji-
dad. El listado pedido se dará como secuencia de parejas, de tipo Sec[Pareja[string, Sec[int]]]. 
7. Añade a la clase TArbinDinamico<TElem> una operación que determine si un árbol binario es un 
montículo. Analiza su complejidad. 
8. Añade a la clase TArbinDinamico<TElem> una operación maxNivel que obtenga el máximo número 
de nodos de un nivel del árbol, esto es, el número de nodos del “nivel más ancho”. Analiza su 
complejidad. 
 3 
9. Se trata de modificar la implementación de la clase TArbus<TClave,TValor> para permitir que en 
un árbol de búsqueda se puedan almacenar distintos valores con la misma clave, lo cual implica 
cambios en el comportamiento de algunas operaciones de los árboles: 
— Al insertar un par <clave, valor>, si la clave ya se encontrase en el árbol, en lugar de sustituir 
el valor antiguo por el nuevo, se asociará el valor adicional con la clave. 
— La operación de consulta, en lugar de devolver el valor asociado con una clave dada, devol-
verá una secuencia con los valores asociados con dicha clave. La secuencia estará ordenada 
según el orden en el que se insertaron los valores en el árbol. 
— La operación de borrado deberá eliminar todos los valores asociados con la clave dada. 
Implementa en C++: 
— Los cambios necesarios en la estructura de datos para permitir la implementación eficiente 
de las operaciones de este nuevo TAD. En la estructura de datos sólo puedes utilizar tipos 
predefinidos de C++; está prohibido el uso de otros TADs. 
— Las operaciones de inserción y consulta, indicando razonadamente la complejidad temporal 
de las implementaciones obtenidas. 
10. En la clase TArbinDinamico<TElem> añade una constructora con el siguiente perfil 
template <class TElem> 
TArbinDinamico::TArbinDinamico (TElem v[], int num ); 
donde num es el número de elementos del array v. La constructora debe generar un árbol semi-
completo con los elementos del array. Indica razonadamente la complejidad temporal de la 
implementación obtenida. 
EDI todo/ejercs T-6.pdf
 1 
Estructuras de Datos y de la Información 
Ingeniería Técnica en Informática de Gestión. Curso 2007/2008 
Hoja de ejercicios número 6 
Tablas 
1. Se trata de enriquecer la clase TTablaAbierta<TClave,TValor> añadiéndole operaciones de recorri-
do que permitan visitar todos los nodos de la tabla sin importar el orden: 
— reinicia, sitúa el punto de interés al “principio” de la tabla. La especificación no fija cuál ha 
de ser el principio de una tabla. 
— esFin, consulta si el punto de interés está al final de la tabla. Si la tabla está vacía esFin ha de 
ser cierto. 
— actual, devuelve una pareja TPareja<TClave,TValor> con el contenido del nodo situado a 
continuación del punto de interés. Es un error consultar por actual cuando esFin es cierto. 
— avanza, mueve una posición hacia delante el punto de interés. Es un error ejecutar avanza 
cuando esFin es cierto. 
Estas operaciones se deben implementar de forma que un bucle como este 
tabla.reinicia(); 
while ( ! tabla.esFin() ) { 
 cout << tabla.actual(); 
 tabla.avanza(); 
} 
recorra todos los elementos almacenados en la tabla. 
Indica qué cambios sería necesario
realizar en la estructura de datos de la clase TTablaAbier-
ta<TClave,TValor> para poder implementar estas operaciones de manera eficiente, sin que por 
ello se perjudique la complejidad de las otras operaciones de las tablas. Describe cómo implemen-
tarías las nuevas operaciones, qué cambios sería necesario realizar en las otras operaciones de las 
tablas y razona la complejidad temporal que obtendrías. 
2. Se trata de desarrollar un TAD TABLA-ORD[C :: ORD, V :: ANY] que represente a las tablas 
ordenadas. Este TAD ofrecerá las siguientes operaciones: 
— Nuevo: crea una tabla vacía. 
— Inserta: añade una clave y un valor a una tabla. Si en la tabla ya se encontrase la clave insertada, 
se sustituirá el valor antiguo por el nuevo. 
— borra: dada una clave y una tabla, elimina dicha clave, y su valor asociado, de la tabla. Si la clave 
no se encuentra en la tabla, se devolverá la tabla sin modificar. 
— está: determina si una clave se encuentra en una tabla dada. 
— consulta: dada una tabla y una clave, obtiene el valor asociado a dicha clave. Es un error consul-
tar por el valor de una clave que no haya sido insertada previamente. 
— minClave: obtiene la menor clave almacena en la tabla. Es un error consultar por la mínima cla-
ve de una tabla vacía. 
— esVacío: determina si una tabla está vacía. 
— enumera: devuelve una secuencia de pares (clave, valor) con el contenido de la tabla ordenado 
por claves. 
Desarrolla en C++ una clase TTablaOrd<TClave,TValor> que implemente este TAD de forma 
que la complejidad de enumera sea O(n), siendo n el número de datos almacenados en la tabla, y se 
perjudique lo menos posible a la complejidad de las otras operaciones. Analiza la complejidad 
temporal de las operaciones. 
Idea: cada nodo de una lista de colisiones formará parte de dos listas, la propia lista de colisiones 
y una lista ordenada doblemente enlazada que contenga todos los nodos de la tabla. De esta for-
ma, cada nodo contendrá tres punteros: el siguiente en la lista de colisiones, además de el 
siguiente y el anterior en la lista ordenada. 
 2 
3. Se trata de desarrollar un TAD MCJTO[A :: ORD] que represente a los multiconjuntos. Un mul-
ticonjunto es un conjunto donde puede haber elementos repetidos. Este TAD ofrecerá las 
siguientes operaciones: 
— Nuevo: crea un multiconjunto vacío. 
— Inserta: añade un elemento al multiconjunto. 
— borra: elimina un elemento del multiconjunto. 
— está: determina si un elemento pertenece al multiconjunto. 
— min: devuelve el menor elemento de entre los que contiene el multiconjunto. 
— borraMin: elimina una aparición del menor elemento del multiconjunto. 
— esVacío: determina si un multiconjunto está vacío. 
Desarrolla en C++ una clase TMultiCjto<TElem> que implemente este TAD intentando minimi-
zar la complejidad temporal de las operaciones. 
Idea: representa los multiconjuntos como tablas ordenadas utilizando los elementos como claves 
y el número de apariciones como valor. 
4. Resuelve de nuevo el problema de las concordancias (cfr. ejercicio 5 de la hoja 5), utilizando en lugar 
de un árbol de búsqueda una tabla ordenada del tipo que hemos considerado en el ejercicio 2. 
Analiza el tiempo de ejecución del algoritmo que obtengas. 
5. Diseña un procedimiento que “limpie” una tabla cerrada, de tal manera que las posiciones borra-
das se eliminen y las restantes informaciones se reubiquen en la tabla. Todas las informaciones 
correspondientes a claves sinónimas deberán quedar situadas en posiciones consecutivas de la su-
cesión de pruebas, a partir de la posición primaria que corresponda. 
6. Modifica la implementación de la operación de inserción en las tablas cerradas vista en clase para 
que cuando la tasa de ocupación supere un cierto valor fijado de antemano, se aumente la capaci-
dad del array, se reubiquen los datos adecuadamente y se “limpie” la tabla. 
Aplicaciones 
Para los siguientes ejercicios has de suponer que todos los TADs vistos en clase están equipados con 
la operación numElem que devuelve el número de elementos de la estructura en cuestión. 
Los árboles de búsqueda, además de la operación recorre que obtiene una secuencia con los valores 
del árbol, estarán equipados también con estas dos operaciones de recorrido: 
TSecuenciaDinamica<TClave> recorreClave( ) const; 
// Pre : true 
// Post : devuelve las claves del árbol ordenadas 
TSecuenciaDinamica< TPareja<TClave,TValor> > recorreClaveValor( ) const; 
// Pre : true 
// Post : devuelve parejas con las claves y los valores del árbol, ordenadas por clave 
Debes considerar así mismo que las tablas (abiertas y cerradas) están equipadas con las siguientes 
operaciones: 
TSecuenciaDinamica< TPareja<TClave, TValor> > enumera( ) const; 
// Pre: true 
// Post: Devuelve una secuencia de parejas con los elementos de la tabla 
TSecuenciaDinamica<TClave> enumeraClave( ) const; 
// Pre: true 
// Post: Devuelve una secuencia con las claves de la tabla 
TSecuenciaDinamica<TValor> enumeraValor( ) const; 
// Pre: true 
// Post: Devuelve una secuencia con los valores de la tabla 
 3 
 
 
7. En este ejercicio se trata de desarrollar un sistema informático que modele el comportamiento de 
un consultorio médico. Para ello suponemos disponibles los módulos que implementan a las siguien-
tes clases, todas ellas equipadas con operaciones de igualdad y orden: 
— TMedico que sirve para almacenar y gestionar la información sobre un médico del consultorio. 
— TPaciente que sirve para almacenar y gestionar la información sobre un paciente. 
Nosotros nos encargaremos de la implementación de la clase TConsultorio, cuya misión es gestio-
nar la información sobre los médicos y las citas de los pacientes. Esta clase ofrece las siguientes 
operaciones públicas: 
— Nuevo: Genera un consultorio vacío sin ninguna información. 
— NuevoMédico: Altera un consultorio, dando de alta a un nuevo médico que antes no figuraba en 
el consultorio. 
— PideConsulta: Altera un consultorio, haciendo que un paciente se ponga a la espera para ser 
atendido por un médico, el cual debe estar dado de alta en el consultorio. 
— siguientePaciente: Consulta el paciente a quien le toca el turno para ser atendido por un médico; 
éste debe estar dado de alta, y debe tener algún paciente que le haya pedido consulta. 
— atiendeConsulta: Modifica un consultorio, eliminando el paciente al que le toque el turno para 
ser atendido por un médico; éste debe estar dado de alta, y debe tener algún paciente que le 
haya pedido consulta. 
— tienePacientes: Reconoce si hay o no pacientes a la espera de ser atendidos por un médico, el cual 
debe estar dado de alta. 
Desarrolla en C++ una implementación de la clase TConsultorio basada en otros TADs conocidos, 
optimizando la complejidad temporal de las operaciones. 
 
8. En este ejercicio se trata de desarrollar un sistema informático que modele el comportamiento de 
un mercado de trabajo simplificado, donde las personas pueden ser contratadas y despedidas por 
empresas. Para ello suponemos disponibles los módulos que implementan a las siguientes clases, 
todas ellas equipadas con operaciones de igualdad y orden: 
— TPersona que sirve para almacenar y gestionar la información sobre una persona. 
— TEmpresa que sirve para almacenar y gestionar la información sobre una empresa. 
Nosotros nos encargaremos de la implementación de la clase TMercado, cuya misión es gestionar 
la información sobre el mercado de trabajo. Esta clase ofrece las siguientes operaciones públicas: 
— Nuevo: Genera un mercado vacío, sin ninguna información. 
— Contrata: Altera un mercado, efectuando la contratación de cierta persona como empleado de 
cierta empresa. 
— despide: Altera un mercado, efectuando el despido de cierta persona que era antes empleado de 
cierta empresa. 
— empleados: Consulta los empleados de una empresa, devolviendo el resultado como secuencia 
ordenada de personas. 
— esEmpleado: Averigua si es cierto o no que una persona dada es empleado
de una empresa dada. 
— esPluriempleado: Averigua si es cierto o no que una persona es empleado de más de una empre-
sa. 
Desarrolla en C++ una implementación de la clase TMercado basada en otros TADs conocidos, 
optimizando la complejidad temporal de las operaciones. 
 4 
9. Nos han encargado desarrollar un sistema informático que se ocupe del almacenamiento y la ges-
tión de citas literarias. La clase TCultura será la encargada de gestionar la información de una 
colección de citas, ofreciendo a sus clientes las siguientes operaciones públicas: 
— Nuevo: inicializa una colección de citas vacía. 
— Inserta: añade una cita a una colección de citas. Una cita viene dada como una cadena (string) 
y se puede suponer que no se insertarán citas repetidas. 
— elimina: dada una secuencia de palabras, que se pueden suponer no repetidas, elimina las ci-
tas que contengan todas esas palabras. 
— consulta: dada una secuencia de palabras, que se pueden suponer no repetidas, devuelve una 
secuencia sin repetición con las citas que contienen dichas palabras. 
— consultaAprox: dada una secuencia de palabras no repetidas y un número n menor o igual 
que la longitud de la secuencia, devuelve una secuencia sin repetición con las citas que con-
tienen al menos n palabras de la consulta. 
Desarrolla en C++ una implementación de la clase TCultura basada en otros TADs conocidos, 
optimizando la complejidad temporal de las operaciones. 
Idea: se puede utilizar una tabla donde cada palabra (clave) lleva asociada la lista de citas donde 
esa palabra aparece (valor). Para evitar repetir las citas se pueden utilizar punteros. 
 
10. Nos han encargado desarrollar un sistema informático que se ocupe de la gestión de las notas de 
los alumnos de la Escuela de Informática de San Petersburgo. Para ello suponemos disponibles 
los módulos que implementan a las siguientes clases: 
— TAsignatura, que sirve para almacenar y gestionar la información sobre una asignatura: el 
nombre de la asignatura, el profesor, el curso en el cual se imparte, …. Suponemos que está 
equipado con operaciones de igualdad y orden. 
— TAlumno, que sirve para almacenar y gestionar la información sobre un alumno: su nombre, 
DNI, domicilio, …. Suponemos también que está equipado con operaciones de igualdad y 
orden. 
— TNota, que sirve para representar las calificaciones obtenidas por los alumnos en las asigna-
turas: sin calificar, no presentado, suspenso, aprobado, notable y sobresaliente. 
Nosotros nos encargaremos de implementar la clase TTablon que ofrece las siguientes operaciones 
públicas: 
— Nuevo: inicializa un Tablon vacío. 
— InsertaAsignatura: añade a un Tablon una asignatura, junto con la lista –o secuencia– de los 
alumnos matriculados en ella. 
— Califica: añade a un Tablón la información sobre la nota de un alumno en una asignatura de-
terminada. 
— listaNotas: devuelve una secuencia ordenada con los alumnos que han aprobado una asigna-
tura, junto con sus notas correspondientes. 
— pendientes: devuelve una secuencia con las asignaturas que un determinado alumno no ha 
aprobado todavía. 
— junio: modifica un Tablon eliminando de él la información relativa a las asignaturas aproba-
das por los alumnos. De esta forma, en el Tablon sólo quedará información sobre las 
asignaturas pendientes de los alumnos. 
Desarrolla en C++ una implementación de la clase TTablon basada en otros TADs conocidos, 
optimizando la complejidad temporal de las operaciones. 
 5 
11. Nos han encargado desarrollar un sistema informático que se ocupe de la gestión de una tienda 
que vende libros por Internet. Para ello suponemos disponibles los módulos que implementan a 
las siguientes clases, todas ellas equipadas con operaciones de igualdad y orden: 
— TCliente, que sirve para almacenar y gestionar la información sobre un cliente: su nombre, 
dirección, …. 
— TLibro, que sirve para almacenar y gestionar la información sobre un libro: su título, autor, 
tema, ISBN, …. 
— TPais, que sirve para representar los países a los que pertenecen los clientes. Suponemos 
que el TCliente está equipada con la observadora país que devuelve el país donde reside el 
cliente. 
— TTema, que sirve para representar los temas de los libros. Suponemos que la clase TLibro 
está equipada con la observadora tema que devuelve el tema al que pertenece el libro. 
Nosotros nos encargaremos de la implementación de la clase TTienda, cuya misión es gestionar la 
información sobre los libros disponibles y sobre los pedidos de los clientes. Esta clase ofrece las 
siguientes operaciones públicas: 
— Nuevo: inicializa una Tienda vacía. 
— InsertaLibro: añade a una Tienda un número determinado de ejemplares de un cierto libro. El li-
bro podía estar ya disponible, con lo que esta operación sólo modificará el número de 
ejemplares, o puede que se trate de un libro nuevo. 
— Pedido: esta operación añade a una Tienda la información de un pedido que ha realizado un 
cliente determinado. La información sobre el pedido está dada como una secuencia de libros. 
Aunque el envío de los libros no se realiza automáticamente al recibirse el pedido, los libros 
solicitados se consideran reservados, por lo que esta operación se deberá encargar de actualizar 
adecuadamente el número de ejemplares disponibles. También puede ocurrir que no haya exis-
tencias de alguno de los libros solicitados, en cuyo caso se retendrá la información sobre el 
pedido del libro o libros en cuestión, para así poder atenderlo en cuanto lleguen más ejempla-
res. Al insertarse nuevos ejemplares de un libro agotado para el que existen pedidos 
pendientes, dichos ejemplares se asignarán respetando el orden en el que se realizaron los pe-
didos. 
— envíoLibros: esta operación consulta y modifica una Tienda para obtener la información sobre 
los pedidos pendientes de envío que tienen como destino a un país determinado, y darlos por 
realizados. Esta operación devuelve una secuencia donde cada elemento contiene los datos de 
un cliente y la secuencia de libros que ese cliente ha pedido (y tiene reservados). Nótese que 
entre los libros a enviar no se pueden incluir aquellos pedidos que están pendientes debido a la 
falta de ejemplares. Nótese asimismo que entre dos envíos sucesivos al mismo país, cada clien-
te puede haber realizado más de un pedido. 
— envíoCatálogo: periódicamente, la librería edita catálogos con las novedades editoriales de un 
cierto tema. Esta operación sirve para consultar una Tienda y obtener la lista de clientes intere-
sados en el tema en cuestión. Se considera que un cliente está interesado en un cierto tema si 
ha comprado más de minLibros libros de dicho tema. 
Desarrolla en C++ una implementación de la clase TTienda basada en otros TADs conocidos, op-
timizando la complejidad temporal de las operaciones. 
 6 
12. Nos han encargado desarrollar un sistema informático que se ocupe de la gestión de los pedidos 
en la pizzería la Pizza Veloz. Para ello suponemos disponibles los módulos que implementan a las 
siguientes clases: 
— TZona, que sirve para representar una zona de la ciudad, y que se utiliza para organizar los en-
víos por zonas. 
— TDireccion, que sirve para representar una dirección concreta. Suponemos que TDireccion ofrece 
una operación zona que devuelve un objeto de tipo TZona con la zona a la que pertenece dicha 
dirección. 
— TPizza, que sirve para representar un tipo de pizza de entre las que se preparan en la Pizza Ve-
loz. 
— THora, que sirve para representar una hora del día. 
— TPedido, que sirve para representar la información sobre un pedido y que está equipado con las 
operaciones: 
— direccion, que devuelve un objeto TDireccion con el destino del envío. 
— cargamento, que devuelve una secuencia de objetos TPizza con las pizzas a enviar. 
— hora, que devuelve la hora en la que se realizó el pedido. 
Nosotros nos encargaremos de la implementación de la clase TPizzeria, cuya misión es
gestionar 
la información sobre los pedidos pendientes. En concreto, esta clase estará equipada con las si-
guientes operaciones públicas: 
— Nuevo: inicializa una TPizzeria vacía. 
— Inserta: añade a una TPizzeria un nuevo pedido (TPedido). 
— comanda: esta operación proporciona la información necesaria para que un motorista cargue su 
moto y atienda a un cierto número de pedidos. El resultado de esta operación será una se-
cuencia de pares <dirección, secuencia de pizzas> que se obtendrá de la siguiente forma: 
— el pedido pendiente más antiguo pasa directamente a formar parte del resultado, 
— la comanda se completa con otros pedidos pendientes de la misma zona que el primero, te-
niendo en cuenta que: (1) se han de atender antes a los pedidos más antiguos, (2) no se 
debe superar el número de maxPizzas que caben en una moto, y (3) no se pueden fraccionar 
pedidos. De esta forma, se van considerando sucesivamente, por orden cronológico, los 
pedidos pendientes a la zona en cuestión e insertándolos en el resultado siempre que no se 
supere el número de maxPizzas. Este proceso se detiene cuando se ha conseguido exacta-
mente una comanda con maxPizzas o cuando se han considerado todos los pedidos 
pendientes de envío a dicha zona. Se puede suponer, por último, que ningún pedido con-
tiene más de maxPizzas. 
Desarrolla en C++ una implementación de la clase TPizzeria basada en otros TADs conocidos, 
optimizando la complejidad temporal de las operaciones. 
13. Nos han encargado desarrollar un sistema informático que se ocupe de la gestión de la reserva de 
películas en un pequeño video club. Para ello suponemos disponibles los módulos que implemen-
tan a las siguientes clases, todas ellas equipadas con operaciones de igualdad y orden: 
— TPelícula, que sirve para representar una de las películas del video club. 
— TCliente, que sirve para representar un socio del video club. 
Nosotros nos encargaremos de la clase TReservas, cuya misión es gestionar la información sobre 
las películas reservadas. Esta clase ofrecerá las siguientes operaciones públicas: 
— nuevo: inicializa un TReservas vacío. 
— reserva: establece que un cliente ha reservado una cierta película. 
— reservasPendientes: consulta cuántas reservas pendientes hay para una cierta película. 
— películasReservadas: consulta qué películas tiene reservadas un cierto cliente. 
— primero: consulta quién es el primer cliente que tiene reservada una cierta película. 
— alquila: elimina la reserva más antigua de una cierta película. 
Desarrolla en C++ una implementación de la clase TReservas basada en otros TADs conocidos, 
optimizando la complejidad temporal de las operaciones. 
 7 
14. Nos han encargado desarrollar un sistema informático que se ocupe de las estadísticas sobre las 
medallas obtenidas en las Olimpiadas. Para ello suponemos disponibles los módulos que imple-
mentan a las siguientes clases: 
— TPais, que sirve para representar un país. 
— TDeporte, que sirve para representar un deporte olímpico. 
— TPrueba, que sirve para representar una prueba concreta de un cierto deporte y que está equi-
pada con la operación deporte que devuelve un objeto TDeporte con el deporte al que pertenece 
dicha prueba. 
— TAtleta, que sirve para representar a un atleta de los que participan en las Olimpiadas y que es-
tá equipada con la operación pais que devuelve un objeto TPais con el país al que pertenece el 
atleta. 
Nosotros nos encargaremos de la clase TMedallero, cuya misión es gestionar la información sobre 
el número de medallas obtenido por los países participantes en las Olimpiadas, y de la clase TMe-
dallas que representa el número de medallas obtenido por un país concreto (cuántas de oro, 
cuántas de plata y cuántas de bronce). La clase TMedallero estará equipada con las siguientes ope-
raciones públicas: 
— Nuevo: inicializa un TMedallero vacío. 
— clasificacion: añade a un TMedallero la información sobre la clasificación de una prueba, dada 
como un objeto TPrueba y una secuencia de objetos TAtleta ordenada por el puesto obtenido 
en dicha prueba. 
— medalleroDeporte: para un deporte dado devuelve una secuencia de pares <TPais, TMedallas> con 
los países que han obtenido alguna medalla en dicho deporte, ordenada por el número de me-
dallas. 
— medallero: devuelve una secuencia de pares <TPais, TMedallas> con los países que han obtenido 
alguna medalla, ordenada por el número de medallas. 
Para obtener el orden en el medallero, se consideran primero el número de medallas de oro, si 
éstas coinciden, se comparan entonces las de plata, y si también coinciden éstas, las de bronce. 
Si coinciden el número de medallas de oro, plata y bronce, entonces no importa el orden. 
Desarrolla en C++ una implementación de las clases TMedallas y TMedallero basada en otros 
TADs conocidos, optimizando la complejidad temporal de las operaciones. 
15. Nos han encargado desarrollar un revisor de textos. Nuestro sistema gestionará una colección 
con palabras del castellano y posibles formas de escribirlas mal, suponiendo que una palabra mal 
escrita se corresponde con una única palabra correcta. El proceso de corrección consistirá en, da-
do un texto, revisarlo palabra por palabra, de forma que si la palabra es correcta entonces se deja 
como está, si no es correcta pero sabemos a qué palabra correcta se refiere la sustituimos, y si el 
sistema no la conoce se deja tal cual. 
La clase TCorrector que implementa el sistema ofrecerá las siguientes operaciones públicas: 
— nuevo: inicializa un TCorrector vacío. 
— insertaPalabra: añade una nueva palabra correcta. 
— insertaError: añade una nueva forma de escribir mal una cierta palabra, es decir, asocia una 
nueva palabra incorrecta con una correcta. 
— revisa: dado un texto representado por una secuencia de palabras, le aplica el proceso de co-
rrección antes descrito, devolviendo el texto corregido junto con una secuencia que 
contenga las palabras que el sistema desconoce –no sabe si son correctas o incorrectas–. 
— diccionario: devuelve una secuencia ordenada alfabéticamente que contenga cada palabra co-
rrecta y las formas posibles de escribirla mal. 
Desarrolla en C++ una implementación de la clase TCorrector basada en otros TADs conocidos, 
optimizando la complejidad temporal de las operaciones. En la implementación está prohibido el 
acceso a los tipos representantes de los TADs que se usen. 
Para cada operación, indica la complejidad temporal que has obtenido. 
 8 
16. Nos han encargado desarrollar un sistema informático que gestione un foro de mensajes. En el 
foro hay dos tipos de mensajes: los que inician una “línea de discusión”, es decir, aquellos mensa-
jes nuevos que no responden a un mensaje anterior; y los que responden a un mensaje previo (ya 
sea una respuesta a otra respuesta o una respuesta a un mensaje inicial). 
La clase TForo que implementa el sistema ofrecerá las siguientes operaciones públicas: 
— una constructora sin parámetros que inicialice un TForo vacío. 
— insertaMensaje: añade un mensaje que inicia una línea de discusión. 
— insertaRespuesta: inserta un mensaje a como respuesta directa a un mensaje previo b. 
— iniciales: obtiene los mensajes almacenados en el foro que han iniciado una línea de discu-
sión. 
— respuestas: obtiene las respuestas directas a un mensaje dado. 
— mensajes: obtiene todos los mensajes del foro. 
Escribe la definición de la clase TMensaje (sólo la interfaz) y desarrolla en C++ una implementa-
ción de la clase TForo basada en otros TADs conocidos, optimizando la complejidad temporal de 
las operaciones. Si en la clase TMensaje decides incluir alguna operación no trivial, entonces has de 
implementar también dicha operación. 
Para cada operación, indica la complejidad temporal que has obtenido. 
17. Nos han encargado desarrollar un sistema informático que gestione un sistema de indexación de 
documentos mediante palabras clave relacionadas. Cuando se inserta un documento, se le asocia
una palabra clave que luego permitirá recuperarlo (decimos entonces que el documento está in-
dexado por esa palabra clave). La misma palabra clave puede tener varios documentos asociados. 
Por otra parte, las palabras clave están relacionadas entre sí por relaciones de dependencia, de 
forma que si la palabra clave c1 depende de la palabra clave c2, entonces cada vez que se consulte 
por c1 se deberán recuperar también los documentos asociados con c2. La relación de dependen-
cia es transitiva (si c1 depende de c2 y c2 depende de c3 entonces c1 depende de c3 ) y antisimétrica 
(si c1 depende de c2 entonces c2 no puede depender de c1). 
La clase TGestor que implementa el sistema ofrecerá las siguientes operaciones públicas: 
— una constructora sin parámetros que inicialice un TGestor vacío. 
— insertaClaves: añade una relación de dependencia entre dos claves dadas. No es necesario que 
las claves hayan sido insertadas previamente en el sistema. Se valorará que esta operación 
compruebe que no se producen ciclos en la relación de dependencia entre claves. 
— insertaDocumento: añade un documento con una palabra clave asociada. No es necesario que 
la clave haya sido insertada previamente. 
— consulta: dada una cierta palabra clave, recupera sus documentos asociados junto con los do-
cumentos asociados con las claves de las que depende directa o indirectamente, si es que 
existen. 
Escribe la definición de la clase TDocumento (sólo la interfaz) y, suponiendo que las palabras clave 
se representan como datos de tipo string, desarrolla en C++ una implementación de la clase TGes-
tor basada en otros TADs conocidos, optimizando la complejidad temporal de las operaciones. Si 
en la clase TDocumento decides incluir alguna operación no trivial, entonces has de implementar 
también dicha operación. 
Para cada operación, indica la complejidad temporal que has obtenido. 
 
 
EDI todo/IntroduccionC++.pdf
 
TEMA 0 
INTRODUCCIÓN AL LENGUAJE C++ 
 
1. El programa “Hola mundo” 
2. Tipos simples 
3. Declaración, inicialización y asignación de variables y constantes 
4. Operadores 
5. Tipos definidos por el programador 
6. Estructuras de control 
7. Procedimientos y funciones 
8. Entrada y salida 
 
 
 
 
Bibliografía: El lenguaje de programación C++. Tercera edición 
Bjarne Stroustrup 
Addison Wesley, 1998 
 
 
Introducción al lenguaje C++ 1 
 
0.1 Hola mundo 
 El programa “Hola mundo” en C++ 
 
#include <iostream> 
using namespace std; 
 
void main( ) 
{ 
 cout << "Hola mundo mundial\n"; 
} 
 
 El programa principal es siempre una función de nombre main. 
 
 Las operaciones de entrada/salida se importan de módulos de la biblioteca 
usando la directiva include. En el ejemplo se ha importado iostream. 
— Los módulos de la biblioteca estándar definen sus identificadores en el espa-
cio de nombres std, por lo tanto, si no se quiere cualificar a los identificado-
res es necesario añadir la sentencia 
using namespace std; 
para así poder escribir cout en lugar de std::cout 
 
 Los delimitadores { } marcan, respectivamente, el principio y el final de una 
función y sirven así mismo para delimitar bloques de código. 
 
 El tipo void representa la ausencia de valor. 
En C++ un procedimiento es una función que devuelve un resultado de tipo 
void. 
 
 Todas las sentencias terminan con el carácter ; 
 
 Las cadenas se escriben entre comillas dobles. 
 
 Para mostrar un mensaje por la salida estándar (la pantalla), se aplica el opera-
dor de inserción << teniendo como primer operando cout (importado de ios-
tream)y como segundo operando el dato que se pretende mostrar. 
 
 
Introducción al lenguaje C++ 2 
 
“Hola mundo” (en C++ Builder 5) 
— File | New ... 
— En el cuadro de diálogo New Items se selecciona Console Wizard 
 
 
 
 
— En el diálogo Console Wizard se aceptan las opciones por defecto 
 
 
 
Introducción al lenguaje C++ 3 
 
— Y ya tenemos un programa ejecutable 
//--------------------------------------------------------------------- 
#pragma hdrstop 
//--------------------------------------------------------------------- 
#pragma argsused 
int main(int argc, char* argv[]) 
{ 
 return 0; 
} 
//--------------------------------------------------------------------- 
sin más que seleccionar Run | Run o pulsar F9. 
— Si el programa no se ha compilado previamente, se compilará al seleccionar 
la orden Run. 
Para compilar se utiliza la orden Project | Compile unit (ALT+F9) para compi-
lar el archivo actual o Project | Make nombre_proyecto (CTRL+F9) para compilar 
todos los archivos de un proyecto. 
— Si añadimos a este esqueleto de programa las líneas de nuestro “Hola mun-
do” 
#include <iostream> 
using namespace std; 
 
int main(int argc, char* argv[]) 
{ 
 cout << "Hola mundo\n"; 
 return 0; 
} 
Si ejecutamos ahora este programa, veremos en Windows una consola de 
MS-DOS que se abre y cierra rápidamente. Para que nos dé tiempo a ver el 
mensaje, podemos añadir una operación de lectura 
int main(int argc, char* argv[]) 
{ 
 char c; 
 
 cout << "Hola mundo\n"; 
 cin >> c; 
 return 0; 
} 
 
Introducción al lenguaje C++ 4 
 
0.2 Tipos simples 
 Los tipos simples más utilizados 
 
— char 
caracteres, los literales se escriben entre comillas simples: ’a’ 
 
— int 
números enteros en el intervalo −32768 .. 32767 
 
— double 
números reales en el intervalo 1.7e−308 .. 1.7e+308 
 
— bool 
valores lógicos true | false 
 
— void 
el tipo del resultado de las funciones que no devuelven resultado 
(i.e., los procedimientos) 
 
Introducción al lenguaje C++ 5 
 
0.3 Declaración, inicialización y asignación de variables 
y constantes 
 Sintaxis 
 tipo lista_de_variables; 
donde lista_de_variables se compone de uno o más identificadores separados 
por comas. 
En los identificadores se distinguen mayúsculas de minúsculas. 
 
 Una declaración puede aparecer en cualquier lugar de un programa, su ámbito 
será local si se declara dentro de una función y global si se declara al nivel más 
externo. 
En general siempre declararemos las variables locales al principio del cuerpo 
de las funciones. 
 
 = es el operador de asignación 
 
 Las variables se pueden inicializar al ser declaradas 
 
 Las constantes se declaran como las variables pero precedidas de la palabra re-
servada const 
 
 Ejemplo 
 
int global = 0; // variable global inicializada 
 
void main( ) 
{ 
 int local1, local2 = 2; // variables locales a la función main 
 const int uno = 1, dos = 2; // declaración de constantes 
 
 local1 = uno; // asignación 
 
 bool b; // evitaremos estas declaraciones 
 b = true; 
} 
 
Introducción al lenguaje C++ 6 
 
0.4 Operadores 
0.4.1 Operadores aritméticos y de manipulación de bits 
 
 Actúan sobre constantes y variables numéricas 
— +, –, *, / : suma, resta, multiplicación y división 
— % : módulo, que sólo está definido para los enteros (int o long) 
— &, |, ^, <<, >> : operaciones bit a bit y-lógica, o-lógica, o-exclusiva, despla-
zamiento a la izquierda y desplazamiento a la derecha 
 
 Cada uno de estos operadores lleva asociado un operador de asignación de la for-
ma op= tal que 
 variable op= expresión 
es equivalente a 
 variable = variable op expresión 
 
 Ejemplo 
 
void main( ) 
{ 
 const int tres = 3; 
 int n = 289898454 % tres; 
 double f = 1.34e-6, g = 6.7; 
 double h = f + g * f; 
 
 n += tres; 
} 
 
 
 
 
Introducción al lenguaje C++ 7 
 
0.4.2 Operadores relacionales y lógicos 
 
 Operadores relacionales 
— ==, != : igual, diferente 
— >, >=, <, <= : mayor, mayor o igual, menor, menor o igual 
 
 Operadores lógicos 
— && : conjunción 
— || : disyunción 
— ! : negación 
 
 Ejemplo 
 
void main( ) 
{ 
 double f = 1.34e-6, g = 1.35e-6; 
 char h, j; 
 bool b = ! (f == g) && (f*3.6 <= g); 
} 
 
 
Introducción
al lenguaje C++ 8 
 
0.4.3 Operadores de incremento y decremento 
 
 Permiten incrementar y decrementar el valor de una variable 
— ++ : incrementa en una unidad 
— – – : decrementa en una unidad 
 
 Tienen dos formas de uso 
— pre-incremento/pre-decremento. 
La variable se incrementa/decrementa antes de evaluar la expresión 
— post-incremento/post-decremento. 
La variable se incrementa/decrementa después de evaluar la expresión 
 
 Ejemplo 
 
void main( ) 
{ 
 int x = 1, y, z; 
 
 ++x; // pre-incremento 
 x++; // post-incremento 
 y = ++x; 
 z = y--; 
} 
 
¿Cuál es el valor de las variables después de la última asignación? 
 
 
Introducción al lenguaje C++ 9 
 
0.5 Tipos definidos por el programador 
 
 Para definir un tipo se utiliza la palabra reservada typedef delante 
 de la declaración de tipo y el nombre del tipo 
typedef declaración_tipo nombre_tipo 
 
 No existe una palabra reservada para introducir la zona de definiciones de tipo 
de un programa. 
Tipos enumerados 
 
 Los tipos enumerados se declaran con la palabra reservada enum seguida de una 
lista de etiquetas encerradas entre llaves { } 
 
 Las etiquetas de un tipo enumerado son en realidad constantes con valor ente-
ro, donde la primera etiqueta toma el valor 0, la segunda el 1, ... 
 
 Ejemplo 
 
typedef int TDiaMes; 
typedef enum {lun, mar, mie, jue, vie, sab, dom} TDiaSemana; 
 
void main( ) 
{ 
 TDiaMes diaMes = 1; 
 TDiaSemana diaSemana = lun; 
 
 diaMes += 2; 
 diaSemana += 2; 
} 
 
 
Introducción al lenguaje C++ 10 
 
Registros 
 
 Los registros se declaran con la palabra reservada struct seguida de la lista de 
declaración de los campos encerrada entre llaves { } y donde los campos se 
separan por ; 
 
struct { 
 nombre_tipo1 nombre_campo1; 
 ... 
 nombre_tipoN nombre_campoN; 
} nombre_tipo 
 
 Ejemplo 
 
typedef int TDiaMes; 
typedef enum {lun, mar, mie, jue, vie, sap, dom} TDiaSemana; 
typedef struct { 
 TDiaMes diaMes; 
 TDiaSemana diaSemana; 
} TDia; 
 
void main( ) 
{ 
 TDia dia; 
 
 dia.diaMes = 1; 
 dia.diaSemana = lun; 
} 
 
 
Introducción al lenguaje C++ 11 
 
Arrays 
 
 Para cualquier tipo T se puede declarar el tipo T[num] que representa a los vec-
tores de num elementos de tipo T, con índices en el intervalo 0 .. num –1 
— num ha de ser una expresión constante 
 
 También es posible declarar una variable de tipo array sin necesidad de definir 
un nuevo tipo, con la siguiente sintaxis 
nombre_tipo identificador[num]; 
 
 Los arrays se pueden inicializar en la declaración proporcionando una lista de 
valores, separados por comas y encerrados entre llaves 
— Si la lista de inicialización contiene menos elementos que la dimensión del 
array el resto de posiciones se inicializan a 0 
 
 Los vectores multidimensionales se declaran como arrays de arrays 
 
 Ejemplo 
 
typedef int TMatriz[2][2]; 
 
void main( ) 
{ 
 int lista[5] = {0, 1, 2, 3, 4}; 
 TMatriz matriz = { {1,1}, {2,2} }; 
 
 matriz[0][0] = lista[0]; 
 cout << matriz[0][0] << matriz[0][1] << matriz[1][0] \ 
 << matriz[1][1] << "\n"; 
} 
 
¿qué se mostraría por pantalla? 
 
Introducción al lenguaje C++ 12 
 
0.6 Estructuras de control 
Selección condicional 
 
 Sintaxis 
 
 if ( condición ) sentencia 
 
 if ( condición ) sentencia else sentencia 
 
 Ejemplos 
 
int x, y; 
 
if (x == y) 
 x = y++; 
 
 
int x, y, z; 
 
if (x == y) 
{ x = y++; 
 z = ++x; } 
else 
 z = x + y; 
 
 
int x, y, z; 
 
if (x == y) 
 z = 2; 
else if (x > y) 
{ z = 1; 
 x++; } 
else 
{ z = 0; 
 y++; } 
 
 
Introducción al lenguaje C++ 13 
 
Selección múltiple 
 
 Sintaxis 
 
 switch ( expresión ) 
 case expresión-constante : sentencia 
 ... 
 default : sentencia 
 
— Se compara secuencialmente la expresión con las expresiones-constantes hasta en-
contrar una que coincida. A partir de ahí, se ejecutan todas las sentencias hasta 
llegar al final o hasta encontrar una sentencia break 
 
— Si ninguna expresión constante coincide con el valor de expresión, se ejecuta la 
sentencia de la cláusula default, si es que la hay 
 
 Ejemplo 
 
int x = 1, y; 
 
switch (x) 
{ case 1: 
 y++; 
 break; 
 case 2: 
 x++; 
 break; 
 default: 
 x++; y++; 
 break; 
} 
 
Introducción al lenguaje C++ 14 
 
Composición iterativa 
 
 Sentencia while 
while ( condición ) sentencia 
 
— Ejemplo: 
 
int x = 10, y = 1; 
 
while (x > y) 
{ x--; 
 y++; } 
 
 
 Sentencia do .. while 
do sentencia while ( condición ); 
 
— Ejemplo: 
 
int x = 10, y = 1; 
 
do 
{ x--; 
 y++; } 
while (x > y); 
 
Introducción al lenguaje C++ 15 
 
 Sentencia for 
for ( inicializaciónopcional; condiciónopcional; expresiónopcional ) 
 sentencia 
— Se ejecuta la inicialización y mientras la condición sea cierta, se ejecuta la sentencia 
y a continuación la expresión 
— Es posible incluir varias inicializaciones, condiciones y/o expresiones separándolas 
por comas 
 
 Ejemplos 
— Este fragmento de código 
 
int a[10], indice; 
 
for (indice = 0; indice < 10; indice++) 
 a[indice] = 2*indice; 
 
es equivalente a este otro 
 
int a[10], indice; 
 
indice = 0; 
while ( indice < 10 ) 
{ a[indice] = 2*indice; 
 indice++; } 
 
— Ejemplo de expresiones compuestas 
 
int a[10], indice, valor; 
 
for (indice = 0, valor = 9; indice < 10; indice++, valor--) 
 a[indice] = valor; 
 
 
 
 
 
 
Introducción al lenguaje C++ 16 
 
0.7 Procedimientos y funciones 
 
 Sintaxis 
 
tipo-resultado nombre ( lista-parámetros ) 
{ 
 lista-de-sentencias 
} 
 
 El resultado de una función se devuelve con la sentencia 
 
return expresión; 
 
que además termina la ejecución de la función 
 
 Un procedimiento es una función cuyo tipo de resultado es void 
 
 Ejemplo 
 
int suma ( int x, int y ) 
{ 
 return x + y; 
} 
 
void main( ) 
{ 
 int x = suma(2, 3); 
} 
 
 
Introducción al lenguaje C++ 17 
 
Paso de parámetros 
 
 Por defecto los parámetros se pasan por valor. 
Para indicar que un parámetro formal es por referencia, se escribe el carácter 
& detrás del nombre del tipo 
Los arrays, por razones de eficiencia, se pasan siempre por referencia 
 
 Es posible utilizar como parámetro arrays abiertos con la sintaxis 
nombre-tipo identificador [ ] 
Así se pueden escribir funciones que pueden recibir un array de cualquier lon-
gitud. Para que la función conozca la longitud del array que se pasa como pa-
rámetro real es habitual pasar un segundo argumento con la longitud. 
 
 También es posible definir valores por defecto para los argumentos 
Los argumentos con valor por defecto deben aparecer siempre al final de la lis-
ta de argumentos 
 
 Ejemplo 
void acumula ( int vector[], int longitud, int& suma ) 
{ 
 int indice; 
 
 for( indice = 0; indice < longitud; indice++ ) 
 suma += vector[indice]; 
} 
 
int suma ( int x, int y = 1 ) 
{ 
 return x + y; 
} 
 
void main( ) 
{ 
 int v[5] = {0, 1, 2, 3, 4}; 
 int s = 0; 
 
 acumula( v, suma(4), s); 
} 
 
Introducción al lenguaje C++ 18 
 
0.8 Entrada y salida 
 Una de las posibles formas de realizar entrada/salida en C++ es por medio de 
los flujos o canales –streams– 
— En el módulo iostream se incluyen las funciones e identificadores estándar pa-
ra el manejo de canales 
 
 En iostream se definen tres canales predefinidos 
— cin, para entrada de datos 
— cout, para salida de datos 
— cerror, para salida de errores 
 
 Los canales se manejan con los operadores de inserción y extracción 
— <<, para enviar datos a un canal 
— >>, para obtener datos de un canal 
 
 Los operadores importados de iostream saben cómo manejar datos de los tipos 
predefinidos 
 
 Ejemplo 
void pesado ( ) 
{ 
 const int magico = 123; 
 int intento; 
 char c; 
 
 cout << “Adivina el número mágico: “; 
 cin >>

Otros materiales