Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


Transparencias Tema 1, Apuntes de Ingeniería del Software

Asignatura: Estructura de los computadores, Profesor: , Carrera: Ingeniería de Software, Universidad: UCM

Tipo: Apuntes

2016/2017

Subido el 17/07/2017

lujarami
lujarami 🇪🇸

3.7

(3)

5 documentos

1 / 13

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
Capítulo 1
Análisis de la eficiencia de los
algoritmos 1
No puede haber orden cuando hay mucha prisa
Seneca
Resumen: En este tema se muestra la importancia de contar con algoritmos eficien-
tes, se define qué se entiende por coste de un algoritmo y se enseña a comparar las
funciones de coste de distintos algoritmos con el fin de decidir cuál de ellos es preferi-
ble. Se define una jerarquía de órdenes de complejidad que ilustra la separación entre
algoritmos eficientes y los que no lo son.
1. Introducción
?Aproximadamente cada año y medio se duplica el número de instrucciones por se-
gundo que son capaces de ejecutar los computadores. Ello puede inducir a pensar
que basta con esperar algunos años para que problemas que hoy necesitan muchas
horas de cálculo puedan resolverse en pocos segundos.
?Sin embargo hay algoritmos tan ineficientes que ningún avance en la velocidad de las
máquinas podrá conseguir para ellos tiempos aceptables. El factor predominante que
delimita lo que es soluble en un tiempo razonable de lo que no lo es, es precisamente
el algoritmo elegido para resolver el problema.
?En este capítulo enseñaremos a medir la eficiencia de los algoritmos y a comparar
la eficiencia de distintos algoritmos para un mismo problema. Después de la correc-
ción, conseguir eficiencia debe ser el principal objetivo del programador. Mediremos
principalmente la eficiencia en tiempo de ejecución, pero los mismos conceptos
son aplicables a la medición de la eficiencia en espacio, es decir a medir la memoria
que necesita el algoritmo.
?El siguiente programa ordena un vector a[0..n 1] por el método de selección:
1Ricardo Peña es el autor principal de este tema.
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd

Vista previa parcial del texto

¡Descarga Transparencias Tema 1 y más Apuntes en PDF de Ingeniería del Software solo en Docsity!

Capítulo 1

Análisis de la eficiencia de los

algoritmos

No puede haber orden cuando hay mucha prisa Seneca

Resumen: En este tema se muestra la importancia de contar con algoritmos eficien- tes, se define qué se entiende por coste de un algoritmo y se enseña a comparar las funciones de coste de distintos algoritmos con el fin de decidir cuál de ellos es preferi- ble. Se define una jerarquía de órdenes de complejidad que ilustra la separación entre algoritmos eficientes y los que no lo son.

1. Introducción

? Aproximadamente cada año y medio se duplica el número de instrucciones por se- gundo que son capaces de ejecutar los computadores. Ello puede inducir a pensar que basta con esperar algunos años para que problemas que hoy necesitan muchas horas de cálculo puedan resolverse en pocos segundos.

? Sin embargo hay algoritmos tan ineficientes que ningún avance en la velocidad de las máquinas podrá conseguir para ellos tiempos aceptables. El factor predominante que delimita lo que es soluble en un tiempo razonable de lo que no lo es, es precisamente el algoritmo elegido para resolver el problema.

? En este capítulo enseñaremos a medir la eficiencia de los algoritmos y a comparar la eficiencia de distintos algoritmos para un mismo problema. Después de la correc- ción, conseguir eficiencia debe ser el principal objetivo del programador. Mediremos principalmente la eficiencia en tiempo de ejecución, pero los mismos conceptos son aplicables a la medición de la eficiencia en espacio, es decir a medir la memoria que necesita el algoritmo.

? El siguiente programa ordena un vector a[0..n − 1] por el método de selección:

(^1) Ricardo Peña es el autor principal de este tema.

2 Capítulo 1. Análisis de la eficiencia

1 int a[n]; 2 int i, j, pmin, temp; 3 for (i = 0; i < n-1; i++) 4 // pmin c a l c u l a l a p o s i c i ó n d e l mínimo de a [ i.. n −1] 5 {pmin = i; 6 for (j = i+1; j < n; j++) 7 if (a[j] < a[pmin]) pmin = j; 8 // ponemos e l mínimo en a [ i ] 9 temp = a[i]; a[i] = a[pmin]; a[pmin] = temp; 10 }

? Una manera de medir la eficiencia en tiempo de este programa es contar cuántas instrucciones de cada tipo se ejecutan, multiplicar este número por el tiempo que emplea la instrucción en ejecutarse, y realizar la suma para los diferentes tipos. Sean

ta = tiempo de una asignación entre enteros (1.1) tc = tiempo de una comparación entre enteros ti = tiempo de incrementar un entero tv = tiempo de acceso a un elemento de un vector

La línea (3) da lugar a una asignación, a n− 1 incrementos y a n comparaciones, es decir, a un tiempo ta + (n − 1)ti + ntc. La línea (5) da lugar a un tiempo (n − 1)ta. El bucle interior for se ejecuta n − 1 veces, cada una con un valor diferente de i. Para cada valor de i y siguiendo el cálculo hecho para la (3), la línea (6) da lugar a un tiempo ta + (n − i − 1)ti + (n − i)tc. La línea (7) da, para cada valor de i, un tiempo mínimo de (n − i − 1)(2tv + tc), suponiendo que la instrucción pmin = j nunca se ejecuta. A ello hay que sumar (n − i − 1)ta en el caso más desfavorable en que dicha rama se ejecute todas las veces. El caso promedio tendrá un tiempo de ejecución entre estos dos. Finalmente, la línea (9) dará lugar a un tiempo (n − 1)(4tv + 3ta). Por tanto, el tiempo del bucle interior for, en el caso más desfavorable, se calcula mediante el siguiente sumatorio: n∑− 2

i=

(ta + tc + (n − i − 1)(ti + 2tv + ta + 2tc)) = P (n − 1) +

Qn(n − 1)

siendo P = ta + tc y Q = ti + 2tv + ta + 2tc.

Para no cansar al lector con tediosos cálculos, concluiremos que la suma de todos estos tiempos da lugar a dos polinomios de la forma:

Tmin = An^2 − Bn + C Tmax = A′n^2 − B′n + C′

donde A, A′, B, B′, C y C′^ son expresiones racionales positivas que dependen lineal- mente de los tiempos elementales descritos en 1.1.

? En este sencillo ejemplo se observan claramente los tres factores de los que en general depende el tiempo de ejecución de un algoritmo:

Estructura de Datos y Algoritmos

4 Capítulo 1. Análisis de la eficiencia

  1. La comparación entre funciones de coste se hará para valores de n suficien- temente grandes, es decir los costes para tamaños pequeños se consideran irrelevantes.

? Sea N el conjunto de los números naturales y R+^ el conjunto de los reales estricta- mente positivos.

Definición 1.1 Sea f : N −→ R+^ ∪ { 0 }. El conjunto de las funciones del orden de f (n), denotado O(f (n)), se define como:

O(f (n)) = {g : N −→ R+^ ∪ { 0 } | ∃c ∈ R+, n 0 ∈ N. ∀n ≥ n 0. g(n) ≤ cf (n)}

Asímismo, diremos que una función g es del orden de f (n) cuando g ∈ O(f (n)). También diremos que g está en O(f (n)).

4 Capítulo 1. Análisis de la eficiencia

3. La comparación entre funciones de coste se hará para valores de n suficien-

temente grandes, es decir los costes para tamaños pequeños se consideran

irrelevantes.

? Sea N el conjunto de los números naturales y R+^ el conjunto de los reales estricta-

mente positivos.

Definición 1.1 Sea f : N ! R+^ [ { 0 }. El conjunto de las funciones del orden de

f (n), denotado O(f (n)), se define como:

O(f (n)) = {g : N ! R+^ [ { 0 } | 9 c 2 R+, n 0 2 N. 8 n n 0. g(n)  cf (n)}

Asímismo, diremos que una función g es del orden de f (n) cuando g 2 O(f (n)).

También diremos que g está en O(f (n)).

n

? N R+

f : N ! R+^ [ { 0 } f (n) O(f (n))

O(f (n)) = {g : N ! R+^ [ { 0 } | 9 c 2 R+, n 0 2 N. 8 n n 0. g(n)  cf (n)}

g f (n) g 2 O(f (n)) g O(f (n))

cf (n) g(n)

?

n O(f (n)) n 0

? g(n)

f (n) g^0 (n)

f (n) O(f (n))

? O(f (n)) f (n)

O(n) O(n^2 ) O(1) O(f (n)) f (n)

?

O(n^2 ) O(n log n)

?

120 n^2 2 n^2 O(n^2 )

? O(f (n)) (n+1)^2 2 O(n^2 )

? Generalizando, admitiremos también que una función negativa o indefinida para un

número finito de valores de n pertenece al conjunto O(f (n)) si eligiendo n 0 suficien-

temente grande, satisface la definición.

? Esta garantiza que, si el tiempo de ejecución g(n) de una implementación concreta

de un algoritmo es del orden de f (n), entonces el tiempo g^0 (n) de cualquier otra

implementación del mismo que difiera de la anterior en el lenguaje, el compilador,

o/y la máquina empleada, también será del orden de f (n). Por tanto, el coste O(f (n))

expresa la eficiencia del algoritmo per se, no el de una implementación concreta del

mismo.

? Las clases O(f (n)) para diferentes funciones f (n) se denominan clases de comple-

jidad, u órdenes de complejidad. Algunos órdenes tienen nombre propio. Así, al

orden de complejidad O(n) se le llama lineal, al orden O(n^2 ), cuadrático, el orden

O(1) describe la clase de las funciones constantes, etc. Eligiremos como represen-

tante del orden O(f (n)) la función f (n) más sencilla posible dentro del mismo.

? Nótese que la definición 1.1 se puede aplicar tanto a un análisis en el caso peor, como

a un análisis en el caso promedio. Por ejemplo, hay algoritmos cuyo coste en tiempo

está en O(n^2 ) en el caso peor y en O(n log n) en el caso promedio.

? Nótese también que las unidades en que se mide el coste en tiempo (horas, segundos,

milisegundos, etc.), o en memoria (octetos, palabras, celdas de longitud fija, etc.) no

son relevantes en la complejidad asintótica: dos unidades distintas se diferencian

en una constante multiplicativa (e.g. 120 n^2 segundos son 2 n^2 minutos, ambos en

O(n^2 )).

? Generalizando, admitiremos también que una función negativa o indefinida para un número finito de valores de n pertenece al conjunto O(f (n)) si eligiendo n 0 suficien- temente grande, satisface la definición.

? Esta garantiza que, si el tiempo de ejecución g(n) de una implementación concreta de un algoritmo es del orden de f (n), entonces el tiempo g′(n) de cualquier otra implementación del mismo que difiera de la anterior en el lenguaje, el compilador, o/y la máquina empleada, también será del orden de f (n). Por tanto, el coste O(f (n)) expresa la eficiencia del algoritmo per se, no el de una implementación concreta del mismo.

? Las clases O(f (n)) para diferentes funciones f (n) se denominan clases de comple- jidad, u órdenes de complejidad. Algunos órdenes tienen nombre propio. Así, al orden de complejidad O(n) se le llama lineal, al orden O(n^2 ), cuadrático, el orden O(1) describe la clase de las funciones constantes, etc. Eligiremos como represen- tante del orden O(f (n)) la función f (n) más sencilla posible dentro del mismo.

? Nótese que la definición 1.1 se puede aplicar tanto a un análisis en el caso peor, como a un análisis en el caso promedio. Por ejemplo, hay algoritmos cuyo coste en tiempo está en O(n^2 ) en el caso peor y en O(n log n) en el caso promedio.

? Nótese también que las unidades en que se mide el coste en tiempo (horas, segundos, milisegundos, etc.), o en memoria (octetos, palabras, celdas de longitud fija, etc.) no son relevantes en la complejidad asintótica: dos unidades distintas se diferencian en una constante multiplicativa (e.g. 120 n^2 segundos son 2 n^2 minutos, ambos en O(n^2 )).

Estructura de Datos y Algoritmos

  1. Medidas asintóticas de la eficiencia 5

? Aplicando directamente la definición de O(f (n)), demostremos que (n+1)^2 ∈ O(n^2 ). Un modo de hacerlo es por inducción sobre n. Elegimos n 0 = 1 y c = 4, es decir demostraremos ∀n ≥ 1. (n + 1)^2 ≤ 4 n^2 : Caso base: n = 1, (1 + 1)^2 ≤ 4 · 12

Paso inductivo: h.i. (n + 1)^2 ≤ 4 n^2. Demostrémoslo para n + 1:

(n + 1 + 1)^2 ≤ 4(n + 1)^2 (n + 1)^2 + 1 + 2(n + 1) ≤ 4 n^2 + 4 + 8n (n + 1)^2 ≤ 4 n^2 + 6︸ ︷︷ ︸n + 1 ≥ 0

? También podemos probar que 3 n^6 ∈ O(2n). Si perteneciera, existiría c ∈ R+, n 0 ∈ N tales que 3 n^ ≤ c · 2 n^ para todo n ≥ n 0. Esto implicaría que ( 32 )n^ ≤ c para todo n ≥ n 0. Pero esto es falso porque dado un c cualquiera, bastaría tomar n > log 1 , 5 c para que ( 32 )n^ > c, es decir ( 32 )n^ no se puede acotar superiormente.

? La notación O(f (n)) nos da una cota superior al tiempo de ejecución t(n) de un algoritmo. Normalmente estaremos interesados en la menor función f (n) tal que t(n) ∈ O(f (n)). Una forma de realizar un análisis más completo es encontrar además la mayor función g(n) que sea una cota inferior de t(n). Para ello introducimos la siguiente medida.

Definición 1.2 Sea f : N −→ R+^ ∪ { 0 }. El conjunto Ω(f (n)), leído omega de f (n), se define como:

Ω(f (n)) = {g : N −→ R+^ ∪ { 0 } | ∃c ∈ R+, n 0 ∈ N. ∀n ≥ n 0. g(n) ≥ cf (n)}

2. Medidas asintóticas de la eficiencia 5

? Aplicando directamente la definición de O(f (n)), demostremos que (n+1)^2 2 O(n^2 ).

Un modo de hacerlo es por inducción sobre n. Elegimos n 0 = 1 y c = 4, es decir

demostraremos 8 n 1. (n + 1)^2  4 n^2 :

Caso base: n = 1, (1 + 1)^2  4 · 12

Paso inductivo: h.i. (n + 1)^2  4 n^2. Demostrémoslo para n + 1:

(n + 1 + 1)^2  4(n + 1)^2

(n + 1)^2 + 1 + 2(n + 1)  4 n^2 + 4 + 8n

(n + 1)^2  4 n^2 + 6| n{z + 1 }

0

? También podemos probar que 3 n^62 O(2n). Si perteneciera, existiría c 2 R+, n 0 2 N

tales que 3 n^  c · 2 n^ para todo n n 0. Esto implicaría que ( 32 )n^  c para todo

n n 0. Pero esto es falso porque dado un c cualquiera, bastaría tomar n > log 1 , 5 c

para que ( 32 )n^ > c, es decir ( 32 )n^ no se puede acotar superiormente.

? La notación O(f (n)) nos da una cota superior al tiempo de ejecución t(n) de un

algoritmo. Normalmente estaremos interesados en la menor función f (n) tal que

t(n) 2 O(f (n)). Una forma de realizar un análisis más completo es encontrar además

la mayor función g(n) que sea una cota inferior de t(n). Para ello introducimos la

siguiente medida.

Definición 1.2 Sea f : N ! R+^ [ { 0 }. El conjunto ⌦(f (n)), leído omega de f (n),

se define como:

⌦(f (n)) = {g : N ! R+^ [ { 0 } | 9 c 2 R+, n 0 2 N. 8 n n 0. g(n) cf (n)}

n = 1 (1 + 1)^2  4 · 12

(n + 1)^2  4 n^2 n + 1

(n + 1 + 1)^2  4(n + 1)^2 (n + 1)^2 + 1 + 2(n + 1)  4 n^2 + 4 + 8n (n + 1)^2  4 n^2 + 6| n{z + 1 } 0

? 3 n^62 O(2n) c 2 R+^ n 0 2 N

3 n^  c · 2 n^ n n 0 ( 32 )n^  c n n 0 c n > log 1 , 5 c ( 32 )n^ > c ( 32 )n

? O(f (n)) t(n)

f (n) t(n) 2 O(f (n)) g(n) t(n)

f : N ! R+^ [ { 0 } ⌦(f (n)) f (n)

⌦(f (n)) = {g : N ! R+^ [ { 0 } | 9 c 2 R+, n 0 2 N. 8 n n 0. g(n) cf (n)}

g(n) cf (n)

? O(f (n))

⌦(f (n))

t(n) O(f (n)) ⌦(g(n)) t(n) c 1 f (n) c 2 g(n) c 1 c 2 n

? g(n) 2 O(f (n))

f (n) 2 ⌦(g(n))

? f (n)

t(n)

⇥(f (n)) f (n)

? Es frecuente confundir la medida O(f (n)) como aplicable al caso peor y la medida

⌦(f (n)) como aplicable al caso mejor. Esta idea es errónea. Aplicaremos ambas

medidas al caso peor (también podríamos aplicar ambas al caso promedio, o al

caso mejor). Si el tiempo t(n) de un algoritmo en el caso peor está en O(f (n)) y en

⌦(g(n)), lo que estamos diciendo es que t(n) no puede valer más que c 1 f (n), ni menos

que c 2 g(n), para dos constantes apropiadas c 1 y c 2 y valores de n suficientemente

grandes.

? Es fácil demostrar (ver ejercicios) el llamado principio de dualidad: g(n) 2 O(f (n))

si y solo si f (n) 2 ⌦(g(n)).

? Sucede con frecuencia que una misma función f (n) es a la vez cota superior e inferior

del tiempo t(n) (peor, promedio, etc.) de un algoritmo. Para tratar estos casos,

introducimos la siguiente medida.

Facultad de Informática - UCM

? Es frecuente confundir la medida O(f (n)) como aplicable al caso peor y la medida Ω(f (n)) como aplicable al caso mejor. Esta idea es errónea. Aplicaremos ambas medidas al caso peor (también podríamos aplicar ambas al caso promedio, o al caso mejor). Si el tiempo t(n) de un algoritmo en el caso peor está en O(f (n)) y en Ω(g(n)), lo que estamos diciendo es que t(n) no puede valer más que c 1 f (n), ni menos que c 2 g(n), para dos constantes apropiadas c 1 y c 2 y valores de n suficientemente grandes. ? Es fácil demostrar (ver ejercicios) el llamado principio de dualidad: g(n) ∈ O(f (n)) si y solo si f (n) ∈ Ω(g(n)).

? Sucede con frecuencia que una misma función f (n) es a la vez cota superior e inferior del tiempo t(n) (peor, promedio, etc.) de un algoritmo. Para tratar estos casos, introducimos la siguiente medida.

Facultad de Informática - UCM

  1. Jerarquía de órdenes de complejidad 7

n log 10 n n n log 10 n (^) n^2 n^3 2 n

10 1 ms 10 ms 10 ms 0. 1 s 1 s 1. 02 s

102 2 ms 0. 1 s 0. 2 s 10 s 16. 67 m (^4). 02 ∗ 1020 sig

103 3 ms 1 s 3 s 16. 67 m 11. 57 d (^3). 4 ∗ 10291 sig

104 4 ms 10 s 40 s 1. 16 d 31. 71 a (^6). 3 ∗ 103000 sig

105 5 ms 1. 67 m 8. 33 m 115. 74 d 317. 1 sig (^3). 16 ∗ 1030093 sig

106 6 ms 16. 67 m 1. 67 h 31. 71 a 317 097. 9 sig (^3). 1 ∗ 10301020 sig

Figura 1: Crecimiento de distintas funciones de complejidad

computador? O lo que es lo mismo, ¿qué ocurre si duplicamos el tiempo disponible?

t(n) t = 1h. t = 2h. k 1 · log n n = 100 n = 10 000 k 2 · n n = 100 n = 200 k 3 · n log n n = 100 n = 178 k 4 · n^2 n = 100 n = 141 k 5 · n^3 n = 100 n = 126 k 6 · 2 n^ n = 100 n = 101

? Observamos que mientras el de coste logarítmico es capaz de resolver problemas 100 veces más grandes, el de coste exponencial resuelve un tamaño practicamente igual al anterior. Obsérvese que los de coste O(n) y O(n log n) se comportan de acuerdo a la intuición de un usuario no informático: al duplicar la velocidad del computador (o el tiempo disponible), se duplica aproximadamente el tamaño del problema resuelto. En los de coste O(nk), al duplicar la velocidad, el tamaño se multiplica por un factor √ k 2.

? En la Figura 2 se muestra la jerarquía de órdenes de complejidad. Las inclu- siones estrictas expresan que se trata de clases distintas. Los algoritmos cuyos costes están en la parte izquierda resuelven problemas que se denominan tratables. Estos costes se denominan en su conjunto polinomiales. Hay problemas que solo admiten algoritmos de complejidad exponencial o superior. Se llaman intratables.

? También hay muchos problemas interesantes cuyos mejores algoritmos conocidos son exponenciales en el caso peor, pero no se sabe si existirán para ellos algoritmos polinomiales. Se llaman NP-completos y se verán en el próximo curso. El más conocido de todos es el problema SAT que consiste en determinar si una fórmula de la lógica proposicional es satisfactible.

Facultad de Informática - UCM

8 Capítulo 1. Análisis de la eficiencia

O(1) ⊂ O(log n) ⊂ O(n) ⊂ O(n log n) ⊂ O(n^2 ) ︸ ︷︷ ︸ razonables en la práctica

⊂... ⊂ O(nk)

︸ ︷︷ ︸ tratables

⊂... ⊂ O(2n) ⊂ O(n!)

︸ ︷︷ ︸ intratables

Figura 2: Jerarquía de órdenes de complejidad

4. Propiedades de los órdenes de complejidad

? O(a · f (n)) = O(f (n)) con a ∈ R+.

(⊆) g ∈ O(a · f (n)) ⇔ ∃c ∈ R+, n 0 ∈ N tal que ∀n ≥ n 0. g(n) ≤ c · a · f (n). Tomando c′^ = c · a se cumple que ∀n ≥ n 0. g(n) ≤ c′^ · f (n), luego g ∈ O(f (n)).

(⊇) g ∈ O(f (n)) ⇔ ∃c ∈ R+, n 0 ∈ N tal que ∀n ≥ n 0. g(n) ≤ c · f (n). Entonces tomando c′^ = (^) ac se cumple que ∀n ≥ n 0. g(n) ≤ c′^ · a · f (n), luego g ∈ O(a · f (n)).

? La base del logaritmo no importa: O(loga n) = O(logb n), con a, b > 1. La demostra- ción es inmediata sabiendo que:

logb n =

loga n loga b

? Si f ∈ O(g) y g ∈ O(h), entonces f ∈ O(h).

f ∈ O(g) ⇒ ∃c 1 ∈ R+, n 1 ∈ N tal que ∀n ≥ n 1. f (n) ≤ c 1 · g(n) g ∈ O(h) ⇒ ∃c 2 ∈ R+, n 2 ∈ N tal que ∀n ≥ n 2. g(n) ≤ c 2 · h(n)

Tomando n 0 = m´ax(n 1 , n 2 ) y c = c 1 · c 2 , se cumple

∀n ≥ n 0. f (n) ≤ c 1 · g(n) ≤ c 1 · c 2 · h(n)

Y por tanto f ∈ O(h).

? Regla de la suma: O(f + g) = O(m´ax(f, g)).

(⊆) h ∈ O(f + g) ⇒ ∃c ∈ R+, n 0 ∈ N. ∀n ≥ n 0. h(n) ≤ c · (f (n) + g(n)). Pero f ≤ m´ax(f, g) y g ≤ m´ax(f, g), luego:

h(n) ≤ c · (m´ax(f (n), g(n)) + m´ax(f (n), g(n))) = 2 · c · m´ax(f (n), g(n))

Tomando c′^ = 2 · c se cumple que ∀n ≥ n 0. h(n) ≤ c′^ · m´ax(f (n), g(n)) y por tanto h ∈ O(m´ax(f, g)).

(⊇) h ∈ O(m´ax(f, g)) ⇒ ∃c ∈ R+, n 0 ∈ N. ∀n ≥ n 0. h(n) ≤ c · m´ax(f (n), g(n)). Pero m´ax(f, g) ≤ f + g, luego h ∈ O(f + g) trivialmente.

? Regla del producto: Si g 1 ∈ O(f 1 ) y g 2 ∈ O(f 2 ), entonces g 1 · g 2 ∈ O(f 1 · f 2 ). La demostración es similar.

Estructura de Datos y Algoritmos

10 Capítulo 1. Análisis de la eficiencia

  1. Si tenemos dos algoritmos con costes t 1 (n) = 3n^3 y t 2 (n) = 600n^2 , ¿cuál es mejor en términos asintóticos? ¿A partir de que umbral el segundo es mejor que el primero?
  2. Si el coste de un algoritmo está en O(n^2 ) y tarda 1 segundo para un tamaño n = 100, ¿de qué tamaño será el problema que puede resolver en 10 segundos?
  3. Demostrar por inducción sobre n ≥ 0 las siguientes igualdades:

a)

∑n i=1 i^ =^ n(n^ + 1)/^2. b)

∑n i=1 i (^2) = n(n + 1)(2n + 1)/ 6. c)

∑n i=1 2 ii = (n − 1)2n+1 (^) + 2.

  1. Demostrar que

∑n i=1 i k (^) ∈ Θ(nk+1).

  1. Demostrar que log n ∈ O(

(n)) pero que

(n) 6 ∈ O(log n).

  1. ¿Verdadero o falso?

a) 2 n^ + n^99 ∈ O(n^99 ). b) 2 n^ + n^99 ∈ Ω(n^99 ). c) 2 n^ + n^99 ∈ Θ(n^99 ). d ) Si f (n) = n^2 , entonces f (n)^3 ∈ O(n^5 ). e) Si f (n) ∈ O(n^2 ) y g(n) ∈ O(n), entonces f (n)/g(n) ∈ O(n). f ) Si f (n) = n^2 , entonces 3 f (n) + 2n ∈ Θ(f (n)). g) Si f (n) = n^2 y g(n) = n^3 , entonces f (n)g(n) ∈ O(n^6 ).

  1. Comparar con respecto a O y Ω los siguientes pares de funciones:

a) 2 n+1, 2 n. b) (n + 1)!, n!. c) log n,

n. d ) Para cualquier a ∈ R+, log n, na.

  1. Supongamos que t 1 (n) ∈ O(f (n)) y t 2 (n) ∈ O(f (n)). Razonar la verdad o falsedad de las siguientes afirmaciones:

a) t 1 (n) + t 2 (n) ∈ O(f (n)). b) t 1 (n) · t 2 (n) ∈ O(f (n^2 )). c) t 1 (n)/t 2 (n) ∈ O(1).

  1. (?) Demostrar o refutar cada una de las siguientes afirmaciones:

a) n^2 + n + log n ∈ O(n^2 ). b) n^2 + n + log n ∈ Ω(n). c) n^2 + n + log n ∈ Θ(log n). d ) 21 n^3 + 7n^2 + n log n − 17 n + 8 ∈ O(n^4 ). e) 2 n^ + 3n^ + n^59 ∈ O(n^59 ). f ) 2 n^ + 3n^ + n^59 ∈ Ω(2n). g) Si f (n) = n^2 , entonces f (n)^3 ∈ Θ(f (n)^3 ).

Estructura de Datos y Algoritmos

Ejercicios... 11

h) Θ(2n) = Θ(2n+2) = Θ(4n). i) log 2 n ∈ O(log 3 n).

  1. (?) Para cada una de las siguientes funciones f (n), obtener el menor número natural k tal que f (n) ∈ O(nk).

a) f (n) = 2n^3 + n^2 log n. b) f (n) = 3n^5 + (log n)^4. c) f (n) = (n^4 + n^2 + 1)/(n^3 + 1). d ) f (n) = (n^4 + n^2 + 1)/(n^4 + 1). e) f (n) = (n^4 + 5 log n)/(n^4 + 1). f ) f (n) = (n^3 + 5 log n)/(n^4 + 1).

  1. (?) Para cada una de las siguientes funciones f (n), encontrar una función g(n) del menor orden posible tal que f (n) ∈ O(g(n)).

a) f (n) = (n log n + n^2 )(n^3 + 2). b) f (n) = (2n^ + n^2 )(n^3 + 3n). c) f (n) = n log(n^2 + 1) + n^2 log n. d ) f (n) = n^2 n

  • nn 2 . e) f (n) = (n! + 2n)(n^3 + log(n^2 + 1)).
  1. (?) Comparar con respecto a O y Ω los siguientes pares de funciones:

a) n^2 + 3n + 7, n^2 + 10. b) n^2 log n, n^3. c) n^4 + log(3n^8 + 7), (n^2 + 17n + 3)^2. d ) (n^3 + n^2 + n + 1)^4 , (n^4 + n^3 + n^2 + n + 1)^3. e) log(n^2 + 1), log n. f ) 2 n+3, 2 n+7. g) 22 n , 2 n 2 .

  1. (?) Indicar cuántas multiplicaciones realizan los siguientes algoritmos para calcular potencias en el caso peor. Indicar también sus ordenes asintóticos. 1 int potencia1( int x, int y){ 2 int p = 1; 3 while (y > 0){ 4 p = p*x; 5 y--; 6 } 7 return p; 8 }

1 int potencia2( int x, int y){ 2 int w = x; int p = 1; 3 while (y > 0){ 4 if (y %2 == 1) p = pw; 5 y = y/2; 6 w = ww;

Facultad de Informática - UCM

Ejercicios... 13

3 for ( int i = 1; i < lista.cont; i++) { 4 nuevo = lista.elems[i]; 5 pos = 0; 6 while ((pos < i) && !(lista.elems[pos] > nuevo)) { 7 pos++; 8 } 9 // pos : í n d i c e d e l p r i m e r mayor ; i s i no l o hay 10 for ( int j = i; j > pos; j--) { 11 lista.elems[j] = lista.elems[j - 1]; 12 } 13 lista.elems[pos] = nuevo; 14 } 15 }

  1. Dada la siguiente función que implementa el algoritmo de ordenación de la burbuja. Indicar el número de instrucciones que ejecuta (ver Ej. 19) y su orden asintótico en los casos mejor y peor. 1 void ordenar(tLista& lista) { 2 bool inter = true ; 3 int i = 0; int tmp; 4 while ((i < lista.cont - 1) && inter) { 5 inter = false ; 6 for ( int j = lista.cont - 1; j > i; j--) 7 if (lista.elems[j] < lista.elems[j - 1]) { 8 tmp = lista.elems[j]; 9 lista.elems[j] = lista.elems[j - 1]; 10 lista.elems[j - 1] = tmp; 11 inter = true ; 12 } 13 if (inter) 14 i++; 15 } 16 }

Facultad de Informática - UCM