Complejidad Algoritmica
Complejidad Algoritmica
Complejidad Algoritmica
ALUMNOS:
ANDREA KATHERINE CHAVEZ RIOS
[Dirección de la compañía]
1
Índice
1) Introducción .......................................................................................................... 3
2) ¿Qué es la complejidad algorítmica? ..................................................................... 3
3) Tiempo de ejecución ...............................................................................................5
3.1) IMPORTANCIA DE LA EFICIENCIA .................................................................... 6
4) Asíntotas ................................................................................................................ 8
5) El tamaño de un problema .................................................................................... 8
6) La complejidad no es un número: es una función................................................. 9
7) Órdenes de Complejidad ....................................................................................... 9
8) Impacto Práctico.....................................................................................................10
9) Reglas Prácticas ...................................................................................................... 13
Sentencias sencillas ................................................................................................... 13
9.1) Secuencia (;) ....................................................................................................... 13
9.2) Decisión (if) ........................................................................................................ 13
9.3) Bucles ................................................................................................................ 14
10) conclusión .............................................................................................................. 18
11) Anexos .................................................................................................................... 19
12) Bibliografía............................................................................................................. 21
2
1) Introducción
Cuando solucionamos un
problema mediante la
construcción de un
algoritmo, normalmente
podemos atacar el
problema desde distintos
puntos de vista, aplicando distintas estrategias, y por tanto, llegando a
soluciones algorítmicas distintas.
Ante un mismo problema, puede haber mejores ideas y peores ideas acerca
de cómo afrontar su solución. En lo que sigue sólo nos ocuparemos de
algoritmos correctos, es decir, que nos llevan a una solución válida del
problema planteado. Dentro de lo que es correcto, el análisis de algoritmos
nos lleva a poder decir si una idea es mejor que otra.
3
La complejidad algorítmica es una
métrica teórica que se aplica a los
algoritmos en este sentido. Es un
concepto que fundamental para todos los
programadores, pero sin embargo, a
menudo se desconoce por completo. En
muchos cursos y libros se elude el tema
porque a menudo se considera farragoso.
4
3) Tiempo de ejecución
requiere
T(N) = t1 + t2*N
5
3.1) IMPORTANCIA DE LA EFICIENCIA
n TIEMPO
10 » 1 décima de segundo
20 » 2 minutos
30 > 1 día
40 > 3 años
50 = 3 570 años
6
n TIEMPO
10 = 1 décima de segundo
20 = 8 décimas de segundo
1000 » 1 día
7
4) Asíntotas
5) El tamaño de un problema
La idea que subyace tras el concepto de complejidad temporal de un algoritmo es,
básicamente, medir cuánto tarda en resolver el problema.
Para resolver cualquier problema, son necesarios unos datos de entrada sobre los que
trabaja el algoritmo y que describen una ocurrencia concreta del problema que queremos
resolver. El algoritmo, finalmente obtiene una o varias soluciones al problema (si es que
el problema tiene soluciones).
Sin embargo, debemos tener en cuenta algunas consideraciones. Por ejemplo, piensa en
un típico algoritmo para ordenar los elementos de un vector. Seguro que conoces alguno.
El algoritmo consta de una serie de instrucciones que se repiten una y otra vez (bucles),
y probablemente, de una serie de selecciones (comparaciones) que hacen que se ejecute
uno u otro camino dentro del algoritmo.
Se hace necesaria una pregunta: ¿Tardará lo mismo un algoritmo de ordenación en
ordenar un vector con 100 valores que uno con 100000 valores?.... Obviamente no. Pues
aquí es donde tenemos que empezar a hablar del tamaño o talla del problema.
Un algoritmo de ordenación debería ser capaz de ordenar un vector con cualquier
número de elementos. Sin embargo, el tamaño del vector incide directamente en el
tiempo que tarda el algoritmo en resolverse.
Pues cualquier problema tiene un tamaño, que es un valor o un conjunto de valores que
se pueden obtener de los datos de entrada y que si varían, normalmente tienen una
repercusión en el tiempo que tardará el algoritmo en finalizar (aunque en algunos casos
no).
Por ejemplo, del problema de ordenar un vector, la talla del problema nos la da el
número de elementos del vector.
En un algoritmo que halle el término n-ésimo de la, la talla nos la da el propio término
número n que queremos hallar.
Cada problema tiene uno o varios valores que determinan su talla.
8
La complejidad se calcula en función de una talla genérica, y no concreta. Por ejemplo,
la complejidad de un algoritmo de ordenación se calcula pensando en un array de
longitud n, y no 5, 120 o 100000.
7) Órdenes de Complejidad
9
Se dice que O(f(n)) define un "orden de complejidad". Escogeremos como
representante de este orden a la función f(n) más sencilla del mismo. Así
tendremos
O(n log n)
10
O(f(n)) N=100 t=2h N=200
n 1h 200 2h
n2 1h 141 4h
n3 1h 126 8h
2n 1h 101 1030 h
Los algoritmos de complejidad O(n) y O(n log n) son los que muestran un
comportamiento más "natural": prácticamente a doble de tiempo, doble de datos
procesables.
11
... si a un programa se le prevé larga vida, hay que pensar que le tocará
mantenerlo a otra persona y, por tanto, conviene tener en cuenta su
legibilidad, incluso a costa de la complejidad de los algoritmos
empleados.
... si podemos garantizar que un programa sólo va a trabajar sobre datos
pequeños (valores bajos de N), el orden de complejidad del algoritmo
que usemos suele ser irrelevante, pudiendo llegar a ser incluso
contraproducente.
f 100 n O(n)
G n2 O(n2)
f n O(n)
g 100 n O(n)
12
... en problemas de cálculo numérico hay que tener en cuenta más
factores que su complejidad pura y dura, o incluso que su tiempo de
ejecución: queda por considerar la precisión del cálculo, el máximo
error introducido en cálculos intermedios, la estabilidad del algoritmo,
etc. etc.
9) Reglas Prácticas
Aunque no existe una receta que siempre funcione para calcular la
complejidad de un algoritmo, si es posible tratar sistematicamente una gran
cantidad de ellos, basandonos en que suelen estar bien estructurados y
siguen pautas uniformes.
secuencia (;)
decisión (if)
bucles
llamadas a procedimientos
Sentencias sencillas
Nos referimos a las sentencias de asignación, entrada/salida, etc. siempre y
cuando no trabajen sobre variables estructuradas cuyo tamaño este
relacionado con el tamaño N del problema. La inmensa mayoría de las
sentencias de un algoritmo requieren un tiempo constante de ejecución,
siendo su complejidad O(1).
9.1) Secuencia (;)
La condición suele ser de O(1), complejidad a sumar con la peor posible, bien
en la rama THEN, o bien en la rama ELSE. En decisiones multiples (ELSE IF,
SWITCH CASE), se tomara la peor de las ramas.
13
9.3) Bucles
En los bucles con contador explícito, podemos distinguir dos casos, que el
tamaño N forme parte de los límites o que no. Si el bucle se realiza un
número fijo de veces, independiente de N, entonces la repetición sólo
introduce una constante multiplicativa que puede absorberse.
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)
14
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)
4.4. Llamadas a procedimientos
La complejidad de llamar a un procedimiento viene dada por la complejidad
del contenido del procedimiento en sí. El coste de llamar no es sino una
constante que podemos obviar inmediatamente dentro de nuestros análisis
asintóticos.
Como medida del tamaño tomaremos para N el grado del polinomio, que es el
número de coeficientes en C. Así pues, el bucle más exterior (1) se ejecuta N
veces. El bucle interior (2) se ejecuta, respectivamente
15
1 + 2 + 3 + ... + N veces = N*(1+N)/2 => O(n2)
Intuitivamente, sin embargo, este problema debería ser menos complejo,
pues repugna al sentido común que sea de una complejidad tan elevada. Se
puede ser más inteligente a la hora de evaluar la potencia xn:
double evalua_2 (double x) {
double resultado= 0.0;
for (int termino= 0; termino < coeficientes.length; termino++) {
resultado+= coeficientes[termino] * potencia(x, termino);
}
return resultado;
}
Un ejemplo de caso peor seria x31, que implica la siguiente serie para j:
31 30 15 14 7 6 3 2 1
cuyo número de terminos podemos acotar superiormente por
2 * eis (log2(j)),
donde eis(r) es el entero inmediatamente superior (este cálculo responde al
razonamiento de que en el caso mejor visitaremos eis(log2(j)) valores pares
de "j"; y en el caso peor podemos encontrarnos con otros tantos números
impares entremezclados).
16
Así y todo, esto sigue resultando estravagante y excesivamente costoso. En
efecto, basta reconsiderar el algoritmo almacenando las potencias de "X" ya
calculadas para mejorarlo sensiblemente:
17
10) conclusión
Antes de realizar un programa conviene elegir un buen algoritmo, donde por bueno
entendemos que utilice pocos recursos, siendo usualmente los más importantes el
tiempo que lleve ejecutarse y la cantidad de espacio en memoria que requiera. Es
engañoso pensar que todos los algoritmos son "más o menos iguales" y confiar en
nuestra habilidad como programadores para convertir un mal algoritmo en un
producto eficaz. Es asimismo engañoso confiar en la creciente potencia de las
máquinas y el abaratamiento de las mismas como remedio de todos los problemas
que puedan aparecer.
En el análisis de algoritmos se considera usualmente el caso peor, si bien a veces
conviene analizar igualmente el caso mejor y hacer alguna estimación sobre un caso
promedio. Para independizarse de factores coyunturales tales como el lenguaje de
programación, la habilidad del codificador, la máquina soporte, etc. se suele trabajar
con un cálculo asintótico que indica como se comporta el algoritmo para datos muy
grandes y salvo algún coeficiente multiplicativo. Para problemas pequeños es cierto
que casi todos los algoritmos son "más o menos iguales", primando otros aspectos
como esfuerzo de codificación, legibilidad, etc. Los órdenes de complejidad sólo son
importantes para grandes problemas.
18
11) Anexos
Fácil de
entender,
codificar y
depurar
Algoritmo
Uso efectivo
de los
recursos del
computador
Menor tiempo de
ejecución cuando se
resuelve un
problema
19
Naturaleza y rapidez
de las instrucciones
maquina Complejidad
de tiempo del
algoritmo
Tiempo
Datos de entrada de complejidad del
tiempo del algoritmo
ejecucion
20
12) Bibliografía
http://www.virtual.unal.edu.co/cursos/sedes/manizales/4060024/Lecciones/Capitulo
%20II/rbasicas.htm
http://es.slideshare.net/rezzaca/u1-analisis-algoritmos-complejidad
www.it.uc3m.es/tlp/materiales/es/2%20compl.pdf
dmi.uib.es/~mascport/tp/perweb/tema1.html
www.lab.dit.upm.es/~lprg/material/apuntes/o/
www.dit.upm.es/~pepe/doc/adsw/apuntes/Complejidad.pdf
21