Primer parcial de EDA Facultad de Informática de Valencia 30 de

Anuncio
Primer parcial de EDA
Facultad de Informática de Valencia
30 de junio de 2010 – Duración 2 horas
No olvides poner el nombre. No utilices lápiz ni tinta roja. Se piden siempre soluciones eficientes.
Pregunta 1 (2,5 puntos) Es bien sabido que en un árbol sólo hay un camino de la raı́z a una hoja
dada. Dado el siguiente definición de árbol binario:
struct nodo {
int v a l o r ;
nodo ∗ i z q , ∗ d e r ;
};
c l a s s ab {
nodo ∗ r a i z ;
public :
ab ( ) ;
...
i n t c o n t a r H o j a s ( i n t k ) const ;
};
Se pide implementar el método contarHojas que cuente el número de hojas del árbol para las que los
valores de nodos del camino de la raı́z hasta ellas sume el valor k, que se le pasa como argumento.
Solución:
i n t nodo : : c o n t a r H o j a s ( i n t k ) const {
int n = 0 ;
k −= v a l o r ;
i f ( ! i z q && ! d e r && k==0) n++;
i f ( i z q ) n += i z q −>c o n t a r H o j a s ( k ) ;
i f ( d e r ) n += der−>c o n t a r H o j a s ( k ) ;
return n ;
}
i n t ab : : c o n t a r H o j a s ( i n t k ) const {
return ( r a i z == 0 ) ? 0 : r a i z −>c o n t a r H o j a s ( k ) ;
}
Pregunta 2 (3 puntos) Nos dan una lista de las coordenadas X e Y de una serie de postes telefónicos.
Sabemos que es posible tender un cable entre dos postes si la distancia euclı́dea entre ellos es menor o
igual a d. Se pide escribir una función que devuelva true si es posible conectar el primer poste con el
último. En caso contrario debe devolver false.
bool c o n e c t a b l e ( double c o o r d e n a d a s [ ] [ 2 ] , // v e c t o r de t a l l a numPostes
i n t numPostes ,
double d ) ; // d i s t a n c i a t o p e para t e n d e r un c a b l e
Solución:
f l o a t s q r ( double x ) { return x∗x ; }
bool c o n e c t a b l e ( double c o o r d [ ] [ 2 ] , i n t numPostes , double t o p e ) {
m f s e t m( numPostes ) ;
f o r ( i n t i =0; i <numPostes ; ++i )
f o r ( i n t j=i +1; j <numPostes ; ++j ) {
float d i s t = s q r t ( sqr ( coord [ i ][0] − coord [ j ] [ 0 ] )+
sqr ( coord [ i ][1] − coord [ j ] [ 1 ] ) ) ;
i f ( d i s t <= t o p e )
m. merge ( i , j ) ;
}
return (m. f i n d ( 0 ) == m. f i n d ( numPostes −1) ) ;
}
Pregunta 3 (2,5 puntos) Tenemos un conjunto de enteros que queremos almacenar en una tabla hash
de 10000 cubetas. Nos dan una función hash de enteros con un argumento tipoHash que permite elegir
el comportamiento de la función:
i n t hash ( i n t v a l o r A d i s p e r s a r , i n t numCubetas , i n t tip oHas h ) ;
Implementa una función que determine qué valor de tipoHash (entre 1 y 100) tendrı́amos que utilizar
en la tabla de dispersión para que almacene los datos y minimice el número de colisiones. En caso de
empate debe devolver el menor valor de tipoHash:
i n t e l e g i r T i p o H a s h ( i n t ∗ datos , i n t numDatos ) ; // d e v u e l v e t i p o de hash
Solución:
i n t e l e g i r T i p o H a s h ( i n t ∗ datos , i n t numDatos ) {
const i n t Cubetas = 1 0 0 0 0 ;
bool usada [ Cubetas ] ;
i n t m i n C o l i s i o n e s = numDatos+1;
i n t mejorTipo ;
f o r ( i n t t i p o =1; t i p o <=100; ++t i p o ) {
int c o l i s i o n e s = 0 ;
f o r ( i n t i =0; i <Cubetas ; ++i )
usada [ i ] = f a l s e ;
f o r ( i n t i =0; i <numDatos ; ++i ) {
i n t pos = hash ( d a t o s [ i ] , Cubetas , t i p o ) ;
i f ( usada [ pos ] ) c o l i s i o n e s ++;
usada [ pos ] = true ;
}
i f ( c o l i s i o n e s <m i n C o l i s i o n e s ) {
minColisiones = c o l i s i o n e s ;
mejorTipo
= tipo ;
}
}
return mejorTipo ;
}
Pregunta 4 (2 puntos)
a) Resuelve la siguiente relación de recurrencia por sustitución e indica el coste (no sirve aplicar el
teorema maestro):
(
1
si n = 1
T (n) =
n
2
T ( 2 ) + n si n > 1
b) Escribe un algoritmo Divide y Vencerás que se ajuste a dicha relación de recurrencia.
Solución:
a)
T (n)
n 2
n 2 n 2
n
n
n
= T ( ) + n2 = T ( 2 ) +
+ n2 = T ( 3 ) + 2 +
+ n2
2
2
2
2
2
2
= ...
i−1
∞
X
X
n
n
1
1
2
≤
T
(
)
+
n
= T ( i ) + n2
j
i
2
2
2
2j
j=0
j=0
{después de i pasos y suponiendo que la talla es potencia de 2}
≤ T (1) + 2n2 ∈ Θ(n2 )
b) Un posible algoritmo que se ajusta a esta ecuación en recurrencia puede ser tan simple como esto:
void f ( i n t n ) {
i f ( n>0) {
f o r ( i n t i =0; i <n∗n ; ++i ) ;
f (n/2) ;
}
}
aunque debemos mencionar que cualquier compilador decente con las opciones adecuadas de optimización deberı́a de ser capaz de eliminar el bucle e incluso las propias llamadas, ası́ que si quieres
estudiar experimentalmente el comportamiento temporal deberás de tenerlo en cuenta.
Descargar