Está en la página 1de 19

3.

3 Tamaño de la entrada de los datos

 La medida del costo de ejecución de un algoritmo depende del


tamaño de la entrada de los datos.

 Es común considerar el tiempo de ejecución de un algoritmo, como


una función.

 Para algunos algoritmos, el costo de ejecución es una función de la


entrada particular de los datos.
– En la función Max, el costo es uniforme sobre todos los problemas de
tamaño n.

– En un algoritmo de ordenación esto no ocurre: Si los datos de entrada ya


estuviesen casi ordenados, entonces el algoritmo trabaja menos.
3.4 Clases de comportamiento asintótico

 Complejidad constante: f(n) = O(1)


– El uso del algoritmo es independiente del tamaño de n.

– Las instrucciones del algoritmo son ejecutadas una cantidad fija de veces.

 Complejidad logarítmica: f(n) = O(log n)


– Se presenta, comúnmente, en algoritmos que resuelven un problema
transformándolo en problemas menores.

– El tiempo de ejecución puede ser considerado como menor que una


constante grande.
 Para n = 1000, log2 1000  10.

– Ejemplo: Busca binaria.


 Complejidad lineal: f(n) = O(n)
– Un pequeño trabajo se realiza sobre cada elemento de entrada.

– Esto es bueno para un algoritmo que tiene que procesar y/o producir n
elementos de entrada y/o salida.

– Ejemplo: Busca secuencial, teste de la planaridad de un grafo.

 Complejidad lineal logaritmica: f(n) = O(nlog n)


– Ocurre en algoritmos que solucionan un problema dividiéndolo en
subproblemas. Luego resuelve cada subproblema y finalmente agrupa las
soluciones.

– Es común en algoritmos basados en el paradigma dividir para conquistar.

– Ejemplo: Ordenación MergeSort.


 Complejidad cuadrática: f(n) = O(n2)
– Ocurre en algoritmos que presentan anillos (loops) uno dentro del otro.

– Es útil en algoritmos que usan datos relativamente pequeño.

– Ejemplo: Ordenación por selección e inserción.

 Complejidad exponencial: f(n) = O(2n)


– No son útiles del punto de vista practico.

– Se presentan cuando en la solución de los problemas se usa la fuerza


bruta.

– Ejemplo: Cartero viajante.


220 = 1048576

 Complejidad factorial: f(n) = O(n!)


– Su comportamiento es mucho peor que el caso exponencial.

– Se presentan cuando se usa la fuerza bruta en la solución del problema.

– 20! = 2432902008176640000
3.5 Jerarquía de funciones

 Del punto de vista asintótico esta dado por:

donde  y c son constantes arbitrarias con

Resultados:
3.6 Casos en complejidad computacional

 Mejor caso:
– Menor tiempo de ejecución sobre todas las entradas de tamaño n.

– Cantidad mínima de pasos para cualquier entrada.

– Esta medida no es muy útil. ¿porque?.


 Peor caso:
– Mayor tiempo de ejecución sobre todas las entradas de tamaño n.

– Máxima cantidad de pasos empleados para cualquier entrada.

– Es una medida mas tratable.

 Caso medio (o caso esperado):


– Media (promedio) de los tiempos de ejecución de todas las entradas de
tamaño n.

– En el análisis de este caso, se supone una distribución de probabilidad


sobre el conjunto de entradas de tamaño n y el costo medio se obtiene con
base en esa distribución.
Ejemplos

1) Registros de un archivo
– Consideremos el problema de accesar a los registros de un archivo.
 Cada registro tiene una única clave que se utiliza para recuperar los registros
del archivo.

– Problema: Dada una clave cualquiera, localizar el registro que contenga tal clave.

– Algoritmo: Busca secuencial.


– Sea f una función de complejidad tal que f(n) denota la cantidad de registros
consultados en el archivo (cantidad de veces que la clave de consulta es
comparada con la clave de cada registro).

Mejor caso:
f(n) = 1
El registro buscado es el primero en ser consultado

Peor caso:
f(n) = n
El registro buscado es el ultimo en ser consultado o no esta presente en el
archivo.

Caso medio:
f(n) = (n + 1)2
2) Mayor y menor elemento: versión 1
– Problema: Hallar el mayor y menor elemento de un vector de enteros A[1: n]; n  1.

– El algoritmo puede ser obtenido de aquel algoritmo que encuentra el mayor


elemento.

void maxmin1(vector A)

max = A[0]; min = A[0]
PARA (i = 1: i  n)
SI ( A[i]  max)
max = A[i]
SI ( A[i]  min)
min = A[i]
FINPARA

Análisis
– Sea f una función de complejidad tal que f(n) es el número de comparaciones entre
los elementos de A, si A tuviera n elementos.

– Luego, para todos los casos:


f(n) = 2(n-1), n > 0.
3.7 Comparación de programas

 Sin considerar las constantes de proporcionalidad, los programas


se evalúan comparando las funciones de complejidad,

 Ejemplos:
– Un programa con tiempo O(n) es mejor que otro programa con tiempo
O(n2).
– Un programa A emplea 100n unidades de tiempo para ser ejecutado, otro
programa B emplea 2n2 . ¿Cuál es el mejor?.
 Depende el tamaño del problema.

 Para n < 50, B es mejor que A.

 Para problemas con:


– n pequeño, es preferible usar aquel programa que presenta O(n 2).

– n grande, O(n) es mejor que O(n 2).


3.8 Técnicas para el análisis de los algoritmos

 Determinar el:
– Tiempo de ejecución puede ser un problema matemático complejo.

– Orden del tiempo de ejecución, sin considerar el valor de la constante,


puede ser una tarea simple.

 En el análisis del algoritmo se usa matemática discreta:


– sumatorias, productos, permutaciones, factoriales, ecuaciones de
recurrencia, etc...
 Las técnicas de análisis de algoritmos son:

– asignación, lectura o escritura: O(1).

– Sucesión de comandos:
 Esta determinado por el mayor tiempo de ejecución de cualquier comando de la
sucesión.

– Comando de decisión: SI
 Tiempo empleado por los comandos que están dentro del comando de
decisión, mas el tiempo para evaluar la condición SI, que es O(1).

– Anillo (loop): PARA


 Suma del tiempo de ejecución del contenido del anillo mas el tiempo para
evaluar la condición de terminación (generalmente O(1)), multiplicado por el
número de iteraciones.
– Procedimientos no recursivos:
 Cada procedimiento debe ser computado separadamente uno a uno, empezando
con los procedimientos que no llaman a otros procedimientos.

 Luego se evalúan los procedimientos que llaman a los procedimientos (los cuales
no llaman a otros procedimientos).

 El proceso se repite hasta llegar al programa principal.

– Procedimientos recursivos:
 Asocia una función de complejidad f(n) desconocida, donde n mide el tamaño de
los argumentos.
Ej.- for (int i= 0; i < K; i++) { algo_de_O(1) } => K*O(1) = O(1)

Si el tamaño N aparece como límite de iteraciones ...


Ej.- for (int i= 0; i < N; i++) { algo_de_O(1) } => N * O(1) = O(n)

Ej.- for (int i= 0; i < N; i++) { for (int j= 0; j < N; j++) { algo_de_O(1) } }
tendremos N * N * O(1) = O(n2)

Ej.- for (int i= 0; i < N; i++) { for (int j= 0; j < i; j++) { algo_de_O(1) } }
el bucle exterior se realiza N veces, mientras que el interior se realiza 1,
2, 3, ... N veces respectivamente.
En total, 1 + 2 + 3 + ... + N = N*(1+N)/2 -> O(n 2)
A veces aparecen bucles multiplicativos, donde la evolución de la
variable de control no es lineal (como en los casos anteriores)
Ej.- c= 1; while (c < N) { algo_de_O(1) c= 2*c; }
El valor incial de "c" es 1, siendo "2 k" al cabo de "k" iteraciones. El
número de iteraciones es tal que 2 k >= N => k= eis (log2 (N)) [el entero
inmediato superior] y, por tanto, la complejidad del bucle es O(log n).
Ej.- c= N; while (c > 1) { algo_de_O(1) c= c / 2; }
Un razonamiento análogo nos lleva a log 2(N) iteraciones y, por tanto, a
un orden O(log n) de complejidad.
Ej.- for (int i= 0; i < N; i++) { c= i; while (c > 0) { algo_de_O(1) c= c/2; } }
tenemos un bucle interno de orden O(log n) que se ejecuta N veces,
luego el conjunto es de orden O(n log n)
 Ejemplo (procedimiento no recursivo)
– Ordenar los n elementos de un conjunto A en orden ascendente:

Ordena (Vector A) O(max{1, n-i})=O(n-i)

INICIO
Por lo tanto:
(1) PARA (i = 1: i < n) O(1) Condición terminación O(1) O((n-i)x(n-1))

(2) min  i; O(1)

(3) PARA (j = i + 1: j  n) O(1)

(4) SI ( A[j - 1] < A[min - 1] ) O(1x(n-i)) = O(n-i)


O(1) O(n-i)
(5) min  j;
FINPARA
/*cambia A[min] y A[i]*/
Cantidad de
(6) x  A[min - 1]; A[min - 1]  A[i - 1]; A[i - 1]  x O(1) iteraciones

FINPARA
FIN n 1

 (n  i ) 
1
n ( n 1)
2  n2
2  n2  O(n 2 )

También podría gustarte