TEMA 1.2. REPASO DE COMPLEJIDAD DE ALGORITMOS

Anuncio
TEMA 1.2. REPASO DE COMPLEJIDAD DE
ALGORITMOS
Estructura de Datos y de la Información
Ingeniería Técnica en Informática de Gestión.
LADE + Ingeniería Técnica en Informática de Gestión
URJC
EDI (ITIG)
Complejidad
URJC
1 / 20
ÍNDICE
1
Introducción
2
Recursos Informáticos: tiempo y espacio
3
Casos para el estudio de la complejidad
4
Medidas asintóticas. Órdenes de complejidad
5
Reglas prácticas para el cálculo de complejidades
EDI (ITIG)
Complejidad
URJC
2 / 20
Introducción
1. INTRODUCCIÓN I
Definición
La complejidad o eficiencia de un algoritmo se define como el orden
de magnitud de los recursos informáticos que requiere el algoritmo
para ser ejecutado.
Utilidad
El estudio de la complejidad de los algoritmos permite evaluar su
coste, y así:
1
Comparar algoritmos entre sí.
2
Averiguar si un algoritmo es factible.
EDI (ITIG)
Complejidad
URJC
3 / 20
Introducción
1. INTRODUCCIÓN II
Aspectos que intervienen en el cálculo de complejidades
Cuáles son los recursos informáticos que hay que estimar
(apartado 2).
En qué casos (para qué tipo de entradas) hay que estimar la
complejidad (apartado 3).
Qué significa calcular el orden de magnitud (apartado 4).
Qué reglas prácticas existen para calcular complejidades
(apartado 5).
EDI (ITIG)
Complejidad
URJC
4 / 20
Recursos Informáticos: tiempo y espacio
2. RECURSOS INFORMÁTICOS I
Recursos considerados
Los recursos informáticos a evaluar son el tiempo (de ejecución)
y/o el espacio (de memoria) requeridos por los algoritmos.
Ambos dependen claramente del tamaño de la entrada, por lo
que se trata de calcular las funciones TA y EA tales que:
TA (n) = tiempo requerido para la ejecución del algoritmo A con una
entrada de tamaño n.
EA (n) = espacio de memoria requerido para la ejecución del
algoritmo A con una entrada de tamaño n.
EDI (ITIG)
Complejidad
URJC
5 / 20
Recursos Informáticos: tiempo y espacio
2. RECURSOS INFORMÁTICOS II
Cómo estimar los recursos
El cálculo del tiempo (similar para el espacio) no debe depender ni del
lenguaje de programación utilizado, ni del compilador, ni de la
máquina elegida. Solución:
TA (n) = número de operaciones básicas que realiza el algoritmo A
con una entrada de tamaño n
donde una operación básica es aquella cuyo tiempo de ejecución se
puede acotar superiormente por una constante, independientemente
del tamaño de la entrada, la máquina, etc.
EDI (ITIG)
Complejidad
URJC
6 / 20
Casos para el estudio de la complejidad
3. CASOS PARA EL ESTUDIO DE LA COMPLEJIDAD
Las funciones TA y EA no sólo dependen del tamaño de la
entrada, sino también de su contenido: ¡no se tarda lo mismo en
ordenar 10 números ya ordenados que en ordenar 10 números
totalmente desordenados!
Los casos de estudio más habituales son los siguientes:
El peor caso, caso extremo en el que el número de operaciones a
ejecutar (o el espacio requerido) es el mayor posible.
El caso medio o caso probabilístico, que representa una situación
intermedia (su evaluación suele requerir técnicas estadísticas).
El cálculo en el peor caso asegura que los recursos reales
consumidos, sea cual sea el contenido de la entrada, nunca
rebasarán el valor calculado.
EDI (ITIG)
Complejidad
URJC
7 / 20
Medidas asintóticas. Órdenes de complejidad
4. MEDIDAS ASINTÓTICAS Y ÓRDENES DE
COMPLEJIDAD I
La complejidad de un algoritmo es importante fundamentalmente
cuando el tamaño de la entrada es grande (si hay que ordenar un
conjunto de 5 elementos, la eficiencia del algoritmo no importa
demasiado, puesto que en cualquier caso será razonable).
Por ello, para analizar las funciones TA o EA bastará con estudiar
su comportamiento asintótico, es decir, cómo se comportan
cuando el tamaño de la entrada, n, es grande.
Existen varias medidas para estudiar el comportamiento
asintótico de una función. Una de las más habituales es la medida
O(f ) (O grande de f ) que se describe a continuación, que permite
obtener cotas superiores.
EDI (ITIG)
Complejidad
URJC
8 / 20
Medidas asintóticas. Órdenes de complejidad
4. MEDIDAS ASINTÓTICAS Y ÓRDENES DE
COMPLEJIDAD II
Definición
Sean f , g : N → R + . Se dice que g es del orden de f , y se denota
g ∈ O(f ), si existen c ∈ R + y n0 ∈ N tales que
∀n ≥ n0 ,
g(n) ≤ c.f (n)
Algunas propiedades útiles
O(logb n) = O(logc n)
g(n) = am nm + am−1 nm−1 + . . . a1 n + a0 ∈ O(nm ) si am 6= 0
P
g(n) = ni=1 c = c.n ∈ O(n)
P
g(n) = ni=1 i = n(n+1)
∈ O(n2 )
2
P
g(n) = ni=1 i 2 = n(n+1)(2n+1)
∈ O(n3 )
6
EDI (ITIG)
Complejidad
URJC
9 / 20
Medidas asintóticas. Órdenes de complejidad
4. MEDIDAS ASINTÓTICAS Y ÓRDENES DE
COMPLEJIDAD III
Conjuntos O(f ) más importantes y su ordenación
O(1)
O(log n)
O(n)
O(np )
O(2n )
O(n!)
complejidad constante
complejidad logarítmica
complejidad lineal
complejidad polinómica (p=2: cuadrática, p=3: cúbica)
complejidad exponencial
complejidad factorial
O(1) ⊂ O(log n) ⊂ O(n) ⊂ O(n log n) ⊂ O(np ) ⊂ O(2n ) ⊂ O(n!)
EDI (ITIG)
Complejidad
URJC
10 / 20
Reglas prácticas para el cálculo de complejidades
5. REGLAS PRÁCTICAS I
Resumen de los apartados anteriores
Calcular la complejidad de un algoritmo A
= estudiar el comportamiento asintótico de las funciones TA /EA
(dependientes del tamaño n de la entrada al algoritmo) en el peor
caso o en un caso medio.
= encontrar una función f : N → R + tal que en el peor caso/caso
medio se tenga TA /EA ∈ O(f ).
Observación
Dado que los conjuntos O(f ) proporcionan cotas superiores, se tratará
de encontrar la menor de todas las funciones f : N → R + tales que
TA /EA ∈ O(f ) (por ejemplo, si TA /EA ∈ O(n2 ), evidentemente también
es TA /EA ∈ O(n3 ), pero ... ¡lo segundo no aporta nada!).
EDI (ITIG)
Complejidad
URJC
11 / 20
Reglas prácticas para el cálculo de complejidades
5. REGLAS PRÁCTICAS II
Consideraciones previas
Todo algoritmo está compuesto por una secuencia de
instrucciones.
Existen unas reglas prácticas para calcular el coste de cada uno
de los posibles tipos de instrucciones.
La complejidad de un algoritmo se basa en el coste de las
instrucciones que lo componen pero el cálculo depende de si el
algoritmo es o no recursivo.
EDI (ITIG)
Complejidad
URJC
12 / 20
Reglas prácticas para el cálculo de complejidades
Reglas para calcular el tiempo de ejecución en el peor caso de
los distintos tipos de instrucciones
REGLA 1: INSTRUCCIONES ELEMENTALES
Se llama instrucción elemental a las operaciones de entrada/salida,
asignaciones y expresiones aritméticas en las que no está involucrada
ninguna variable que dependa del tamaño de la entrada del algoritmo.
[I ≡ instrucción elemental] ⇒ TI ∈ O(1)
REGLA 2: SECUENCIAS DE INSTRUCCIONES


I ≡ I1 ; I2
 TI ∈ O(f1 )  ⇒ TI ∈ O(max(f1 , f2 ))
1
TI2 ∈ O(f2 )
EDI (ITIG)
Complejidad
URJC
13 / 20
Reglas prácticas para el cálculo de complejidades
REGLA 3: INSTRUCCIONES DE SELECCIÓN

I ≡ SI B ENTONCES I1 SI NO I2

 TB ∈ O(fB )
 ⇒ TI ∈ O(max(fB , f1 , f2 ))


 TI ∈ O(f1 )
1
TI2 ∈ O(f2 )



I ≡ CASO E EN caso-1: I1 . . . caso-k: Ik
 TE ∈ O(fE )
 ⇒ TI ∈ O(max(fE , fi ))
TIi ∈ O(fi ), i ∈ {1, . . . , k }
EDI (ITIG)
Complejidad
URJC
14 / 20
Reglas prácticas para el cálculo de complejidades
REGLA 4: INSTRUCCIONES DE REPETICIÓN




fiter
I ≡ MIENTRAS B HACER J
X
 fiter ≡ núm. iteraciones (peor caso)  ⇒ TI ∈ O 
fi 
i=1
TB;J ∈ O(fi ) en la iteración i
Nota: la complejidad de un bucle
PARA i DESDE a1 HASTA a2 HACER J
se calcula igual que la de un bucle MIENTRAS salvo que en el caso
PARA el coste de la condición B se puede ignorar puesto que es
siempre constante.
EDI (ITIG)
Complejidad
URJC
15 / 20
Reglas prácticas para el cálculo de complejidades
REGLA 5: LLAMADAS A SUBPROGRAMAS
En el caso de instrucciones que sean llamadas a otros algoritmos
(subprogramas), el coste de la instrucción será el coste del
subprograma:
I ≡ llamada a un subprograma P ⇒ TI = TP
EDI (ITIG)
Complejidad
URJC
16 / 20
Reglas prácticas para el cálculo de complejidades
Cálculo del tiempo de ejecución en el peor caso de un algoritmo
Depende de si el algoritmo es o no es recursivo.
SI EL ALGORITMO ES NO RECURSIVO
Su complejidad es el máximo de las complejidades de las
instrucciones que lo componen (la complejidad de cada una de estas
instrucciones se calcula aplicando las reglas anteriores).
EDI (ITIG)
Complejidad
URJC
17 / 20
Reglas prácticas para el cálculo de complejidades
SI EL ALGORITMO ES RECURSIVO
Para calcular la complejidad de un algoritmo recursivo es
necesario realizar los dos siguientes pasos:
1
2
Plantear la ecuación recurrente asociada con el tiempo de
ejecución T del subprograma.
Resolver la ecuación recurrente anterior (es decir, encontrar una
expresión no recursiva para el valor de T).
Las familias de recurrencias más habituales son:
1
2
Ecuaciones recurrentes obtenidas mediante sustracción
Ecuaciones recurrentes obtenidas mediante división
EDI (ITIG)
Complejidad
URJC
18 / 20
Reglas prácticas para el cálculo de complejidades
Recurrencias obtenidas mediante sustracción
T(n) =
cnk
aT(n − b) + cnk
si 0 ≤ n < b
si n ≥ b
a = número de llamadas recursivas que se realizan
n − b = tamaño de los subproblemas generados
cnk = coste de las instrucciones que no son llamadas recursivas
Solución:
(
T(n) ∈
EDI (ITIG)
O(nk +1 )
O(an div b )
Complejidad
si a = 1
si a > 1
URJC
19 / 20
Reglas prácticas para el cálculo de complejidades
Recurrencias obtenidas mediante división
T(n) =
cnk
aT(n/b) + cnk
si 1 ≤ n < b
si n ≥ b
a = número de llamadas recursivas que se realizan
n/b = tamaño de los subproblemas generados
cnk = coste de las instrucciones que no son llamadas recursivas
Solución:

 O(nk )
T(n) ∈
O(nk log n)

O(nlogb a )
EDI (ITIG)
Complejidad
si a < bk
si a = bk
si a > bk
URJC
20 / 20
Descargar