View
86
Download
0
Category
Preview:
Citation preview
Unidad II
Tema 4: Análisis de Algoritmos
Profesor: Jorge Escalona / Tobías Bolívar
Email: escaljorge@gmail.com / tobiasbolivar@gmail.com
Página Web: http://estructuradatos.tripod.com
Complejidad Computacional
• Complejidad Computacional
• Límites asintóticos
• Notación O
• Planteamiento de ecuaciones de recurrencia
• Solución de ecuaciones de recurrencias
Objetivos
• El alumno calculará la complejidad de un algoritmo: en el peor de los casos, en el promedio de los casos, y en el mejor de los casos, y determinará sus límites asintóticos.
• Dados dos algoritmos, el alumno determinará bajo que circunstancias uno es mejor que otro, basándose en los tiempos de corrida y la complejidad asintótica de ambos.
Medidas de Desempeño
• Cantidad de almacenamiento principal requerido por sus variables
• Cantidad de tráfico que genera en una red de computadoras
• Cantidad de información que debe moverse desde y hacia las unidades de almacenamiento secundario
• Simplicidad del algoritmo
• Tiempo de cómputo
Tiempo de Ejecución de un Algoritmo
A B C D E F G
ENTRADA
5 min
4 min
3 min
2 min
1 min
TIE
MP
O
Peor Caso
Mejor Caso
Caso Promedio?
Medición del Tiempo de Ejecución de un
Algoritmo
•Cómo podemos medir el tiempo
de ejecución de un algoritmo?
•Estudio Experimental:
• Escribir un programa que
implemente el algoritmo.
• Ejecutar el programa con un
conjunto de datos de tamaño y
composición variable.
• Usar algún método para obtener
una medida precisa del tiempo de
ejecución actual. Ejemplo Java: System.CurrenTimeMillis()
• El estudio experimental presenta algunos inconvenientes:
• Es necesario implementar y probar el algoritmo para
determinar su tiempo de ejecución.
• El experimento puede ser hecho sólo sobre un conjunto limitado de entradas, por lo que puede no ser indicativo sobre otros conjuntos de entradas no
contempladas en el experimento.
• Para poder comparar dos algoritmos, debe usarse el
mismo ambiente de hardware y software.
Medición del Tiempo de Ejecución de un
Algoritmo
• Como alternativa, se puede utilizar una metodología general para analizar el tiempo de ejecución de un
algoritmo que:
• Use una descripción de alto-nivel del algoritmo en vez
de una implementación.
• Tome en consideración todos los posibles conjuntos de entrada
• Permita evaluar la eficiencia de un algoritmo,
independientemente de la plataforma de hardare y software en el que se implemente.
Medición del Tiempo de Ejecución de un
Algoritmo
Medición del Tiempo de Ejecución de un
Algoritmo
• Operaciones primitivas: operaciones de bajo nivel que pueden ser comúnmente implementadas en la mayoría de
los lenguajes de programación y que pueden ser
identificadas en pseudo-código.
• Llamar a un procedimiento o función;
• Ejecutar una operación aritmética (ej. una suma);
• Comparar dos números, etc.
• Inspeccionando el pseudo-código se puede contar el
número de operaciones primitivas ejecutadas por un algoritmo.
Medición del Tiempo de Ejecución de un
Algoritmo
Ejemplo:
Algoritmo ArregloMaximo(A,n)
Entrada: un arreglo A guardando números enteros
Salida: el elemento máximo de A
Max ← A[0] (1 vez)
for i ← 1 to n - 1 do (n veces)
if Max < A[i] then (n-1 veces en peor caso)
Max ← A[i] (n-1 veces en peor caso)
return Max (1 vez)
Complejidad Temporal
Definición: el tiempo requerido (unidades de tiempo)
por un algoritmo para procesar una entrada de tamaño
n.
Sea T(n) el tiempo de corrida de algún programa,
debemos asumir:
1. El argumento n es un entero no negativo, y
2. T(n) es no negativo para todos los argumentos de n
Complejidad constante
Cuando la complejidad del algoritmo puede expresarse como
una función constante T(n)=a, se dice que es constante, no
depende de n.
Ejemplo 1: El procedimiento, eleva al cubo, recibe n y
regresa el cubo de n. T(n)=c1
1c1return n*n*n;
# de vecesCostoint eleva al cubo (int n)
Complejidad lineal
Cuando la complejidad de un algoritmo puede
expresarse como una función lineal
T(n)=an + b
donde a y b son constantes se dice que es
lineal en n.
Complejidad lineal
Ejemplo2: El siguiente procedimiento inicializa un arreglo de
n elementos.
6.
5.
nc44. i++
nc33. A[i]=1;
n+1c22. while (i<=n)
1c11. i=1;
# de veces Costovoid inicializa(int *A, int n)
Complejidad lineal
T(n) = c1 + (n+1)c2 + nc3 + nc4
= nc2 + nc3 + nc4 + c1 + c2
= (c2+c3+c4)n + (c1+c2)
= an + b
Si asignamos el valor de una unidad de tiempo para cada instrucción, la complejidad del procedimiento inicializa es T(n)=3n+2 y es lineal.
Complejidad cuadrática
Cuando la complejidad de un algoritmo puede
expresarse como una función cuadrática del tipo
T(n)=an2+bn+c
donde a, b y c son constantes, se dice que el
algoritmo es cuadrático en n.
Complejidad cuadrática
Ejemplo 3: Analicemos el siguiente código.
1. for(i=1; i<=n-1; i++)
2. for(j=1; j<=n-1; j++)
3. A[i,j]=1;
Ciclo Interno:
c1 + c2(n) + c3(n-1) + c4(n-1) = 1 + n + 2(n-1) =3n – 1
Ciclo Externo:
c1 + c2(n) + c3(n-1) + (3n - 1)(n-1) =
1 + 2n - 1 + 3n2 -3n - n + 1= 3n2 - 2n + 1
Casos de Complejidades
• Complejidad en el mejor de los casos: se define T(n) como el tiempo mínimo de corrida para todas las entradas de tamaño n.
• Complejidad en el peor de los casos: se define T(n) cómo el tiempo máximo de corrida para todas las entradas de tamaño n.
• Complejidad promedio: otra medida común de desempeño es Tavg(n), el tiempo promedio de corrida del programa sobre todas las entradas de tamaño n. Aún cuando el tiempo promedio es una medida más realista, en la práctica es más difícil de calcular que el peor de los casos.
El peor de los casos
• Es un límite superior del tiempo de corrida
• Frecuentemente ocurre
• Es más fácil de calcular que el promedio.
Notación Asintótica
Cuando observamos entradas de tamaño lo suficientemente grandes para que sólo el orden de crecimiento de la complejidad sea relevante, estamos estudiando la eficiencia asintótica de los algoritmos.
Casos de Complejidades
•Para especificar la cota superior de la razón de crecimiento de T(n) se
usa la notación O(f(n)).
Formalmente, decimos que T(n) es O(f(n)) si existe un entero n0 y una
constante c > 0 tal que para todos los enteros n ≥ n0, tenemos que
0
2000
4000
6000
0 1 10 50 100 500 1000
T(n)=3n+2
cf(n)
Notación O mayúscula
0 ≤ T(n) ≤ cf(n).
0
5000
10000
15000
20000
25000
30000
35000
1 2 5 10 50 100 500 1000
T(n)=3(n log n)
cf(n)=3logn
Notación Ω
• Para especificar la cota inferior de la razón de crecimiento de T(n)
se usa la notación Ω(f(n)).
• Formalmente, decimos que T(n) es ΩΩΩΩ(f(n)) si existe un entero n0 y una constante c > 0 tal que para todos los enteros n ≥ n0, tenemos que 0 ≤ cf(n) ≤ T(n).
•Ejemplo: 0 ≤ n2 ≤ 2n2 ≤ 3n2
0
500000
1000000
1500000
2000000
2500000
3000000
3500000
10 50 100 500 1000
T(n)=2n^2)
c1f(n)=n^2
c2f(n)=3n^2
Notación Θ
•Formalmente, decimos que T(n) es ΘΘΘΘ(f(n)) si existe un entero n0 y las constantes c1 y c2 > 0 tal que para todos los enteros n ≥n0, tenemos que:
0 ≤ c1f(n) ≤ T(n) ≤ c2f(n)
•Instrucciones secuenciales simples:s1; s2; …. ; sk•Complejidad es O(1)
•Ciclos simples:
for(i=0;i<n;i++) s;
donde s is O(1)
•Complejidad es n O(1) o O(n)
•Ciclos anidados:for(i=0;i<n;i++)
for(j=0;j<n;j++) s;
•Complejidad es n O(n) or O(n2)
Análisis de Complejidad de un Algoritmo
Análisis de Complejidad de un Algoritmo
•Ciclos con índice que no varían linealmenteh = 1;
while ( h <= n )
s;
h = 2 * h;
•h toma valores 1, 2, 4, … hasta que excede a n
• Hay 1 + log2n iteraciones
• Complejidad es O(log n)
Análisis de Complejidad de un Algoritmo
•Ciclos con índices que dependen de otro índice de un
ciclo externo:
for(j=0;j<n;j++)
for(k=0;k<j;k++)
s;
•Ciclo interno se ejecuta
1, 2, 3, …., n veces
•Complejidad es O(n2)
Se debe distinguir este casodonde el contador de la iteraciónse incrementa (o decrementa)
por una constante O(nk)del caso previo donde el índice
cambia por un factor O(log
n)
ΣΣΣΣ i =i=1
n(n+1)
2
Principios generales para la notación O
1. Factores constantes no importan. Para cualquier constante positiva d y cualquier función T(n),
T(n) es O(dT(n)).
2. Términos de orden menor, no importan. Suponga que T(n) es una función polinomial de forma:
aknk + ak-1n
k-1 +...+ a2n2 + a1n + a0
donde akn es positivo. Entonces podemos concluir que T(n) es O(nk)
La regla de la suma
• Suponga que un programa consiste de dos partes, una de
las cuales es de complejidad O(n2) y la otra de O(n3). En
muchos casos como este, es posible sumar estas dos
complejidades usando la regla de la suma:
• Suponga que T1(n) es de O(f1(n)), mientras que T2(n) es de
O(f2(n)), además suponga que f2 no crece tan rápido como
f1; esto es f2 es de O(f1). Entonces podemos concluir que
T1(n) + T2(n) es O(f1(n)).
La regla de la suma
1. readln(n);
2. for i:=1 to n do
3. for j:=1 to n do
4. A[i,j]:=0;
5. for i:=1 to n do
6. A[i,i]:=1;
T1(n)=1 es =O(1), T2(n)=O(n2), T3(n)=O(n)
T1(n)+T2(n)+T3(n) es de O(n2)
Complejidades comunes
Notación O Nombre
O(1) Constante
O(log n) Logarítmico
O(n) Lineal
O(n log n) n log n
O(n2) Cuadrático
O(n3) Cúbico
O(2n) Exponencial
Comparación de algoritmos
• Suponga que para algún problema tenemos la opción de utilizar un programa lineal A cuyo tiempo de corrida es TA(n)=100n (milisegundos requeridos) o un programa cuadrático B cuyo tiempo de corrida es TB(n)=2n2.
• Si TA(n)=100n, en un segundo 1000=100n puedo procesar una entrada de tamaño n=10, mientras que con TB(n)=2n2 una de tamaño 1000=2n2
proceso n=(500)1/2 ≈ 22.3 = 22 elementos
Comparación de algoritmos
Tiempo
(segundos)
Máximo tamaño del
problema que se puede
resolver con A
Máximo tamaño del
problema que se puede
resolver con B
1 10 22
10 100 70
100 1000 223
1000 10000 707
1) Cuál algoritmo es más eficiente para un problema de tamaño 30?
2) Cuál algoritmo es más eficiente para un problema de tamaño 80?
3) Cuál algoritmo es más eficiente para un problema de tamaño 100 000?
4) A partir de qué valor el algoritmo A es más eficiente que el algoritmo B?
Tema 4: Autoevaluación
x:= 0
s := n*n
for i := 1 to n
for j := s downto 1 do
x := x +2
1. Analizar el Tiempo de Ejecución T(n) y la complejidad O(n), de los siguientes fragmentos de
código:
a) for i := 1 to n do
x = x * x
for i := 1 to x do
y := y * x
b)
x := 1while i <= n do
j = n;while j > i do
x := x * xj := j div 4
endi := i + 2
end
c)while i < n
s = f(i)
i = i * 2
end
Nota: T(f(i)) = O(n2)
d)
2. Un algoritmo A resulve un problema de tamaño n en tiempo en n minutos. Otro algoritmo
B resuelve el mismo problema de tamaño n en n3 milisegundos. Haga una tabla
comparativa de los tiempos de ejecución de estos algoritmos para problemas de tamaño
10, 100, 1000, 10000, 100000, 1000000....Cuál de los dos es mejor? Bajo que
circunstancias seleccionará al algoritmo A o al algoritmo B?
Recommended