2. Introducción
• La complejidad de un algoritmo es una forma
de evaluar qué tan rápido se ejecuta un
algoritmo o programa.
• El análisis de complejidad permite comparar
dos algoritmos, de manera independiente de
su implementación y nos permite explicar
cómo se comporta a medida que aumentan
los datos de entrada.
3. Introducción
• Para analizar el comportamiento de un
algoritmo debemos contar cuántas
instrucciones fundamentales ejecuta el
pedazo de código que estamos analizando.
• Para contar cuántas instrucciones hay,
tenemos que encontrar las instrucciones
sencillas que pueden ser ejecutados
directamente por la UCP
4. Instrucciones básicas
• Supondremos que nuestro procesador puede
ejecutar las siguientes instrucciones por
separado.
• Asignar un valor a una variable
• Buscar el valor de un elemento particular de un
arreglo
• Comparar dos valores
• Incrementar un valor
• Operaciones aritméticas básicas
5. Analicemos este fragmento de código
int M = A[0]
for (int i=0; i<n;i++) {
if (A[i] >= M) {
M = A[i];
}
}
Buscar, asignar = 2 instrucciones
1ª iteración: asignación y comparación =
2 instrucciones
Sig. “n” iteraciones: comparación e incremento
=2 instrucciones
Buscar y comparar = 2 instrucciones
Si entra al if: encontrar y asignar
= 2 instrucciones
*pero no siempre ocurre*
El ciclo for sin ninguna instrucción tiene f(n) = 4 + 2*n instrucciones.
La cantidad de instrucciones con el if no pueden definirse tan
fácilmente
6. Análisis del peor caso
• f(n) no puede definirse tan fácilmente por que
la cantidad de instrucciones no sólo depende
de “n” sino también de la entrada.
• Si A=[1,2,3,4]
• Si A=[4,3,2,1]
• ¿Qué es lo peor que puede ocurrir con
nuestro algoritmo? ¿Cuándo se requerirá la
mayor cantidad de instrucciones?
7. Análisis del peor caso
• En el ejemplo, el peor caso es cuando M tiene
que reemplazarse cada vez, y genera la mayor
cantidad de instrucciones en el for.
• f(n)=4 + 2n + 4n =6n+4
• Esta función f, dado un tamaño “n” del
problema, entrega el número de instrucciones
que serán necesarias en el peor de los casos.
8. Comportamiento asintótico
• No siempre es necesario contar las
instrucciones, además de que la cantidad real
de instrucciones depende del compilador y el
lenguaje de programación.
• Ahora encontraremos la función “f” a través
de un filtro.
9. Comportamiento asintótico
• En la función 6n + 4 tienen 2 términos: 6n y 4
• Queremos ver cómo se comporta el algoritmo
cuando se le trata de forma ruda (peor
escenario) lo cual es bastante útil cuando
comparamos algoritmos.
• De los términos de la función vamos a ignorar
los que crecen lentamente y mantendremos
los que crecen rápidamente conforme “n” se
incrementa.
10. Comportamiento asintótico
• En nuestra función dejaremos el término 6n.
• También ignoraremos a la constante que
multiplica a “n”. f(n)=n
• Esto de eliminar los factores y mantener el
término de mayor crecimiento, es lo que
denominamos “comportamiento asintótico”
• El comportamiento asintótico de f(n)=4+6n es
f(n)=n.
15. //ordenar arreglo
for (int l = 0; l<99; l++){
pos_m = inicial(k, l);
if (k[l]>k[pos_m]){
m = k[pos_m];
for (int g = pos_m - 1; g >= 1; g--){
k[g + 1] = k[g];
}
k[l] = m;
}
for (int h = 0; h<100; h++)
cout << k[h] << "t";
cout << endl;
}
. . .
//parte del ordenamiento de insercion
int inicial(int o[], int c){
int p = c;
int d = o[c];
for (int h = c; h<100; h++){
if (o[h]<d){
d = o[h];
p = h;
}
}
return p;
}