Você está na página 1de 12

¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

¿QUE ES LA
COMPLEJIDAD DE UN
ALGORITMO?

INDICE
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?....................................................................2
INTRODUCCION...........................................................................................................................2
EL TAMAÑO DE UN PROBLEMA...............................................................................................3
LA COMPLEJIDAD NO ES UN NUMERO: ES UNA FUNCION...............................................4
PEOR CASO, MEJOR CASO.........................................................................................................6
ASINTONAS Y ORDENES DE COMPLEJIDAD.........................................................................7
ORDENES DE COMPLEJIDADES MAS COMUNES.................................................................8
OPERACIONES CON LA COMPLEJIDAD..................................................................................9
RESUMEN, CONCLUSIONES Y RECOMENDACIONES.......................................................10

Página 1
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

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.
Desde el punto de vista computacional, es necesario disponer de alguna forma de comparar una
solución algorítmica con otra, para conocer cómo se comportarán cuando las implementemos,
especialmente al atacar problemas "grandes".
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.
Pero eso no es necesariamente cierto. La complejidad de un algoritmo es un concepto complicado
pero sólo desde un punto de vista estrictamente formal. La obtención y el estudio de la complejidad
de un algoritmo requiere ciertamente de unas cuantas destrezas matemáticas que no todos tenemos y
la aplicación de una serie de técnicas bastante particulares. Sin embargo, no es un concepto difícil
de entender.
En éste artículo (algo más largo de lo habitual) intentamos ver qué es la complejidad de un
algoritmo y cuales son las situaciones más comunes.

INTRODUCCION

Por hacer una similitud acerca de lo complicado que es este concepto, la dificultad de la
complejidad es -salvando las distancias- como la de la predicción meteorológica: todos intuimos lo
complicado que es hacer una predicción meteorológica... miles de datos, fórmulas, modelos y
cálculos... sin embargo, cuando un meteorólogo nos explica con algo de gracia la predicción del
tiempo, la podemos entender bastante bien. Ya estamos muy acostumbrados a cosas como borrasca,
anticiclón, marejadilla, cota de nieve... Lo mismo pasa en cierto modo con la complejidad:
enfrentarnos a un algoritmo para hacer un estudio de su complejidad requiere de un gran esfuerzo.
Sin embargo, cuando alguien estudia un algoritmo y nos habla de su complejidad, entender el
concepto no es tan complicado.
Entender la complejidad es importante porque a la hora de resolver muchos problemas, utilizamos
algoritmos ya diseñados. Saber valorar su valor de complejidad puede ayudarnos mucho a conocer
cómo se va a comportar el algoritmo e incluso a escoger uno u otro.
Así que en este artículo, nos vamos a dedicar a intentar exponer qué es la complejidad de un
algoritmo desde un punto de vista sencillo y sin pretensiones, intentado distinguir qué impacto tiene
el que un algoritmo tenga una u otra complejidad. Y, como de costumbre, adoptamos grandes
simplificaciones, con el único ánimo de obtener una visión general de los conceptos. En cuanto a
cómo obtener la complejidad de un algoritmo... no nos vamos a meter mucho: los formalismos
necesarios quedan totalmente fuera del alcance de éste breve artículo divulgativo.
Primeramente, debemos tener claro qué es un algoritmo. Podemos entender por algoritmo una
secuencia de intrucciones cuyo objetivo es la resolución de un problema. El término clave aquí es

Página 2
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

el de problema.
Existen multitud de problemas de computación que se pueden resolver mediante un algoritmo.
Bueno... pues para resolver cada problema, podemos obtener más de un algoritmo que lo
solucione... pero... ¿Cual de ellos es el mejor? Sería conveniente poder aplicar algún tipo de
"puntuación" a los algoritmos, y que cuanta más puntuación sacara un algoritmo, pues supondremos
que es mejor. Eso es, en cierto modo, la complejidad.
Saber si un algoritmo es mejor que otro puede estudiarse desde dos puntos de vista: un algoritmo es
mejor cuanto menos tarde en resolver un problema, o bien es tanto mejor cuanta menos memoria
necesite.
A la idea del tiempo que consume un algoritmo para resolver un problema le llamamos
complejidad temporal y a la idea de la memoria que necesita el algoritmo le llamamos
complejidad espacial.
La complejidad espacial, en general, tiene mucho menos interés. El tiempo es un recurso mucho
más valioso que el espacio. (Esto lo podemos ver también en el mundo real: si tienes dinero puedes
comprarte una casa más grande, pero no puedes comprarte unos cuantos años más de vida).
Así que cuando hablamos de complejidad a secas, nos estamos refiriendo prácticamente siempre a
complejidad temporal.
Bueno... pues ya hemos presentado de manera intuitiva esto de la complejidad: la complejidad de un
algoritmo es un "valor", por así decirlo, que nos da una idea de cuánto va a tardar un algoritmo en
resolver el problema para el que fue diseñado.

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 numero 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

Página 3
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

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 sucesión de Fibonacci, la talla nos la dá el
propio término número n que queremos hallar.
Cada problema tiene uno o varios valores que determinan su talla.
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.

LA COMPLEJIDAD NO ES UN NUMERO: ES UNA FUNCION

Otra consideración a tener en cuenta a la hora de tratar con la complejidad es que si estamos
contando el tiempo que tarda un algoritmo en resolver un problema ¿En qué ordenador lo
ejecutamos? Parece obvio que el mismo algoritmo ejecutado en un ordenador el doble de rápido que
otro tardará la mitad en encontrar la solución. ¿Cuál debería ser entonces la unidad de medida de la
complejidad? Ninguna unidad de tiempo nos vale: ni segundos ni milisegundos, porque el resultado
variaría de un ordenador a otro.
Además... parece obvio también que el mismo algoritmo tardará más o menos en solucionar un
problema de una talla u otra. Es decir, no puede tardarse lo mismo en ordenar un array de 100
valores que uno de 100000.
Bueno... pues vamos a adoptar una simplificación que nos permita no tener en cuenta en qué
ordenador se ejecutará el algoritmo: en lugar de medir tiempos, vamos a contar las instrucciones
que debe realizar el algoritmo. Supondremos que cada instrucción se ejecuta en un tiempo
constante.
Nos podemos permitir esa simplificación porque lo que realmente queremos saber es cómo crece el
número de instrucciones necesarias para resolver el problema con respecto a la talla del problema.
Eso es realmente la complejidad.
Por ejemplo, observa ésta función (da igual cuál sea su propósito).

Ejemplo 1

Página 4
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

En este algoritmo hay un par de bucles para que se ejecutan uno después del otro.
Observemos el primer bucle. Se ejecuta n veces, y en su interior hay una instrucción (la de la línea
5). Eso quiere decir que la línea 5 se ejecuta n veces. Después se ejecuta el segundo bucle, que
contiene en su interior dos instrucciones (las de las líneas 8 y 9). Como ese segundo bucle se ejecuta
también n veces y tiene dos instrucciones, se realizan 2n instrucciones. Finalmente hay una
instrucción en la línea 11 que se ejecuta una sola vez.
Bien.... el número de instrucciones que se ejecutan en total son n+2n+1... es decir, 3n+1
Todavía no hemos llegado al fondo de la cuestión, pero vamos encaminados. Podemos decir que la
complejidad de ese algoritmo es 3n+1, porque ese es el número de instrucciones que hay que
realizar para solucionar el problema cuando la talla del problema es n.
La idea que subyace es que podemos saber cómo se comporta el algoritmo conforme la talla del
problema va creciendo. En este caso, si representamos 3n+1 con respecto a n nos daremos cuenta de
que esta función es una recta. Para este algoritmo podemos suponer que cuando lo traslademos a un
lenguaje de programación concreto sobre un ordenador concreto, si para un n=100 tarda 7 unidades
de tiempo en solucionarlo, con unas pocas operaciones podemos deducir cuántas unidades de
tiempo tarda para un n=1000. Por supuesto, no es un valor exacto, pero lo que nos importa es saber
de qué manera aumenta el tiempo con respecto a la talla del problema.
Para terminar de ver la importancia de esto, vamos a ver un par de funciones más de ejemplo.

Ejemplo 2

Ilustración 1: Ejemplo 3

La función ejemplo2 realiza siempre 3 instrucciones (las líneas 4, 5 y 6), independientemente de lo


que se le pase como parámetro. Así pues, este algoritmo siempre tarda lo mismo para cualquier
valor de n. El número de instrucciones se mantiene constante, a diferencia del ejemplo anterior, que
crecía linealmente con respecto a n.
La función ejemplo3 tiene dos bucles para anidados. Cada bucle se ejecuta n veces, y en el interior
del segundo hay 2 instrucciones. Ej bucle interior hace que las dos instrucciones se repitan n veces,
y el bucle exterior hace que todo eso se repita n veces más. Después hay una última instrucción (la

Página 5
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

de la línea 10). Así pues, se hacen 2×n×n+1 instrucciones... es decir, 2n2+1.


Si representamos 2n2+1 con respecto a n en un gráfico nos podemos dar cuenta de que es una
parábola... es decir, el tiempo crece muchísimo más rápido conforme crece n que en los ejemplos
anteriores. En este caso, el tiempo crece cuadráticamente. Igual que ocurría en los ejemplos
anteriores, si en una determinada máquina para n=100 se tardan 7 unidades de tiempo, con unas
pocas operaciones podemos intuir cuánto va a tardar para un n=1000 o para cualquier otro valor.
Lo importante de la idea expuesta hasta ahora es que los distintos algoritmos se comportan de forma
distinta. Su tiempo de ejecución varía de manera muy distinta conforme aumenta la talla del
problema.
Quizá éste gráfico resulte más clarificador.
El eje horizontal representa a la talla del problema (n), y el eje vertical al número de instrucciones
necesarias de nuestros tres ejemplos.
La línea verde corresponde al primer ejemplo. Su número de instrucciones, y por tanto su tiempo de
ejecución crece linealmente conforme n se hace más grande.
La línea azul corresponde al segundo. El número de instrucciones necesarias se mantiene constante,
por muy grande que sea n.
La línea granate corresponde al tercer ejemplo. El
número de instrucciones crece proporcionalmente al
cuadrado de n conforme crece n.
Independientemente de los valores numéricos, resulta
evidente que cada gráfica crece de manera distinta. A
medida que n se vaya haciendo grande, las tres
gráficas se distanciarán cada vez más.
Eso es lo que nos importa realmente de un algoritmo:
saber cómo crece el número de instrucciones a
realizar conforme lo apliquemos cada vez a
problemas más grandes, más que el tiempo medido
en segundos.

PEOR CASO, MEJOR CASO


En los tres ejemplos que hemos visto hasta ahora, la complejidad del algoritmo es totalmente
dependiente de la talla, pero no todos los algoritmos se comportan de igual manera frente a un
problema de la misma talla.
En la mayor parte de los algoritmos, también influye el propio contenido de los datos. Es posible
que para un problema determinado de tamaño n, unas veces el algoritmo tarde más y otras tarde
menos, dependiendo de los propios datos de entrada del problema de tamaño n.
Un ejemplo... Éste algoritmo comprueba si un determinado valor x está contenido en un array v,
cuyos índices van de 1 a n

Página 6
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

Ejemplo 4

Contiene en su interior un bucle mientras que no se ejecuta un número determinado de veces (como
ocurría en los ejemplos anteriores, que utilizaban bucles for). Imagina que pasamos a esa función un
vector de n=100 enteros, y un entero x=17. Es evidente que la talla del problema es n=100, ya que
es lo que determina el número de instrucciones que se ejecutarán. Sin embargo, es posible que el
valor 17 esté situado en la posición 30 del vector, con lo que el bucle se realizará 30 veces, o quizá
en la posición 50, o quizá no esté en el vector, con lo que el bucle se ejecutará n=100 veces,
recorriendo todo el vector.
En éste caso, nos conviene distinguir dos métricas: qué es lo peor que nos puede pasar para un
problema de tamaño n, y qué es lo mejor que nos puede pasar para un problema de tamaño n.
Vamos a echar unas pocas cuentas para el ejemplo de arriba. Vamos a suponer que en el interior del
bucle mientras hay 2 instrucciones (el si y el incremento de i), y en el exterior hay 3, dos antes del
mientras y una después.
Pues bien... lo mejor que nos puede pasar es que encontremos el valor x a la primera. En ese caso, el
bucle se ejecuta una sola vez.. El número de instrucciones que realizamos son 3+2=5.
Lo peor que puede pasar es que el valor x no se encuentre en el vector, así que el bucle se ejecutará
n veces, recorriendo todo el vector. El número de instrucciones que realizamos es 3+2n
Para expresar esto, se utiliza una notación específica, diremos que para este algoritmo, su
complejidad en el peor caso es O(2n+3) A esta notación se le denomina "O Grande" (del inglés
"Big-O"), o simplemente "Complejidad en el peor caso". Aunque es una "O", realmente viene de la
letra griega Omicron. Fue introducida por el matemático Paul Gustav Heinrich Bachmann.
Análogamente, diremos que para este algoritmo su complejidad en el mejor caso es Ω(5). A esta
notación se le denomina "Omega" (por la letra griega omega mayúscula Ω) o simplemente,
"complejidad en el mejor caso".
En general, cuando decimos "complejidad" a secas, casi siempre nos referimos a la complejidad en
el peor caso. Es decir... cuánto va a tardar el algoritmo como mucho.

ASINTONAS Y ORDENES DE COMPLEJIDAD

Ya tenemos una ligera idea informal de qué es la complejidad. Pero entonces ¿Cómo se comparan
unos algoritmos con otros? Bueno... la idea de la complejidad de un algoritmo, es conocer cómo se

Página 7
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

comporta el tiempo de ejecución conforme la talla del problema va creciendo.... especialmente para
valores muy grandes... lo más grandes que podamos imaginar, y especialmente en el peor de los
casos.
En ese contexto de tallas muy grandes podemos hacer otra "simplificación", por así decirlo. El
hecho es que podemos encontrar ciertas similitudes entre las funciones que definen la complejidad
de los algoritmos. Por ejemplo, si comparamos todos los algoritmos cuya complejidad es lineal (es
decir, una recta... por ejemplo: 10n+3, 32n+12, 56n+1... o cualquier otro) y los comparamos con
todos aquellos cuya complejidad es cuadrática (Por ejemplo, 2n2+3, 4n2+n, 6n2+4n+3...) y
dibujamos sus funciones de complejidad en una gráfica observaremos que conforme n se va
haciendo grande, tienen un patrón de crecimiento bien diferenciado.
En ese contexto, podemos agrupar todas las complejidades que crecen igual en el mismo saco. A ese
saco le vamos a llamar orden de complejidad. Hablando un poco más formalmente, para todas las
funciones que agrupemos en un mismo orden, encontraremos una asíntota que al multiplicarla por
un valor nos acote a nuestra función superiormente cuando estemos tratando el peor caso.
Por ejemplo, todas las complejidades cuadráticas están acotadas asintóticamente por "n2". Eso
quiere decir que para cualquiera de las complejidades cuadráticas que hemos visto antes, por
ejemplo 6n2+4n+3, existe un valor real c que hace que 6n2+4n+3 ≤ cn2 cuando n se hace muy
grande, es decir, cuando n→∞
De esta manera, la complejidad suele clasificarse en una serie de órdenes comunes.
La notación para expresar esto es como sigue: Por ejemplo, para decir que 6n2+4n+3 está
determinado por la asíntota superior n2, decimos "que 6n2+4n+3 pertenece al órden de n2" o "que
6n2+4n+3 es del órden de n2" y lo escribimos formalmente de ésta manera:
6n2+4n+3 ∈ O(n2)
Como ves, finalmente el concepto de complejidad se nos simplifica mucho. En lugar de hallar los
tiempos exactos que tarda un algoritmo en solucionar los problemas, con lo que nos quedamos en
con una asíntota que representa a todos los algoritmos cuyo tiempo crece de igual forma cuando la
talla del problema tiende a infinito. Eso hace que el cálculo de la complejidad se simplifique mucho.
Si no queremos hallar la función de complejidad real (y casi nunca queremos), sino el orden al que
pertenece la complejidad del algoritmo, a la hora de hallarla, prácticamente ni siquiera tenemos que
contar las instrucciones... Cada secuencia de instrucciones se cuenta como una sola instrucción. Lo
que influye en la complejidad son principalmente los bucles y las sentencias de selección que tienen
efecto sobre los bucles. En los algoritmos recursivos, la cosa se complica un poco más... Pero como
hemos dicho al principio, el cálculo de la complejidad de un algoritmo queda fuera del alcance de
éste artículo.
Cuando decimos que la complejidad de un algoritmo es de un orden concreto, por ejemplo n2,
podemos estar seguros de que para cualquier valor de n, y por muy mal que nos vayan las cosas
(peor caso), el valor que obtengamos nunca será mayor que cn2, siendo c un real mayor que 1.

ORDENES DE COMPLEJIDADES MAS COMUNES

Página 8
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

Como ya hemos mencionado, la complejidad, digamos "real" en el peor caso de los algoritmos
puede enmarcarse en un "orden de complejidad". Dicho de otra manera, la complejidad de un
algoritmo "crece como" el representante de su orden cuando la talla del problema se hace muy
grande.
Bien... pues los órdenes de complejidad que se suelen manejar son éstos, de mejor a peor.

ORDEN NOMBRE COMENTARIO


O(1) constante Todos aquellos algoritmos que responden en un tiempo constante, sea
cual sea la talla del problema. Son los que aplican alguna fórmula
sencilla, por ejemplo, hallar el máximo de dos valores
O(log n) logarítmico Los que el tiempo crece con un criterio logarítmico,
independientemente de cuál sea la base mientras ésta sea mayor que 1.
Por eso, normalmente, ni siquiera se indica la base. No suelen ser
muchos, y normalmente están bien considerados, ya que implican que
un bucle realiza menos interacciones que la talla del problema, lo cual
no suele ser muy común. Por ejemplo, la búsqueda dicotómica en un
vector ordenado.
O(n) lineal El tiempo crece linealmente con respecto a la talla. Por ejemplo,
encontrar el máximo de un vector de talla n.
O(n log n) enelogarímico, Éste orden tiene muchos nombres. Es un orden relativamente bueno,
loglineal, porque la mayor parte de los algoritmos tienen un orden superior. En
linearítmico o éste orden está, por ejemplo, el algoritmo de ordenación Quicksort, o
simplememente n la transformada rápida de Fourier.
por logaritmo de n
O(nc), con c>1 polinómico Aquí están muchos de los algoritmos más comunes. Cuando c es 2 se
le llama cuadrático, cuando es 3 se le llama cúbico, y en general,
polinómico. Intuitivamente podríamos decir que éste órden es el
último de los aceptables (siempre y cuando c sea relativamente bajo).
A partir del siguiente, los algoritmos son complicados de tratar en la
práctica cuando n es muy grande.
O(cn), con c>1 exponencial Aunque pudiera no parecerlo, es mucho peor que el anterior. Crece
muchísimo más rápidamente.
O(n!) factorial Es el típico de aquellos algoritmos que para un problema complejo
prueban todas las combinaciones posibles.
O(nn) combinatorio Tan intratable como el anterior. A menudo no se hace distinción entre
ellos.

Hay otros órdenes intermedios, e incluso superiores... (realmente, tantos como queramos), pero
usualmente se suelen utilizar los de la tabla de arriba, que son órdenes bastante representativos.
Lo que estamos haciendo, al escoger esos órdenes es particionar todas las posibles complejidades en
una serie de "clases de complejidad". Por supuesto, a su vez, cada una de esas "clases de
complejidad" podría volverse a dividir en distintas subclases, pero eso puede convenirnos algunas
veces y otras no es práctico, por lo menos desde una visión general. Por ejemplo, el órden
exponencial contiene a O(2n) y a O(3n) y a O(4n)... etc. Lo mismo ocurre con (nc), que contiene a
O(n2), y a O(n3) .... y a O(n1000)...

Página 9
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

Para la complejidad en el mejor caso se utilizan los mismos órdenes, sólo que en lugar de utilizar la
letra O (Omicron) para denotarla se utiliza Ω (Omega).
Así pues, por ejemplo, para el algoritmo de ejemplo que obtenía si un valor x estaba en un array de
tamaño n, decimos que su complejidad (en el peor caso) está en el orden O(n) y (en el mejor caso)
en el orden Ω(1).

OPERACIONES CON LA COMPLEJIDAD

Hay muchas operaciones referidas a estos órdenes de complejidad que se pueden aplicar, pero en
general, vamos a comentar algunas de las más sencillas. Todas ellas tienen que ver con el cálculo de
límites. Estas reglas nos permiten "simplificar".... y dado un orden de complejidad, poder llegar a
uno de los de la tabla anterior.

Página 10
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

Es decir, si por ejemplo obtengo que la complejidad de un algoritmo es 6n3+5n+1, es correcto decir
que la complejidad de ese algoritmo es del orden de O(6n3+5n+1), ya que todas la funciones de ese
orden, incluida 6n3+5n+1 están asintóticamente acotadas por ella. Pero con esas reglas, también
podemos decir que la complejidad es del orden de O(6n3+5n), y también del O(6n3) y también del
órden O(n3), porque
O(6n3+5n+1) ⊂ O(6n3+5n) ⊂ O(6n3) ⊂ O(n3)
Pero normalmente, nos basta con saber que un algoritmo tiene un orden O(n3), que es uno de los
órdenes de uso común en lugar de afinar más y decir que el orden es O(6n3+5n+1) porque
realmente cuando n es grande no nos aporta nada afinar más.

RESUMEN, CONCLUSIONES Y RECOMENDACIONES

Bueno... al final no ha sido tan difícil. Resulta que un algoritmo que resuelve un problema con una
determinada talla (por ejemplo, n) tarda un tiempo, en general, mayor en obtener la solución cuanto
mayor es esa talla n (cosa que resulta obvia). La complejidad es una medida que nos da una idea de
cómo es ese crecimiento, resultando que para la mayor parte de algoritmos, ese crecimiento se
puede enmarcar en un determinado "orden", ya que todas las funciones que están en un orden
crecen de manera similar cuando los valores de la talla se van haciendo grandes.
Para cada algoritmo, son interesantes un par de medidas de complejidad: en el peor caso (que
señalamos con la notación O (Omicron, "Big-O"), y en el mejor, para el que utilizamos la notación
Ω (Omega). En especial, suele ser más imprescindible conocer el peor caso, ya que nos da una idea
de qué es lo que puede pasar cuando las cosas van realmente mal.
Toda esta teoría de la complejidad, que tuvo un gran auge hace algunos años, ha sido criticada
desde muchos puntos de vista. La verdad es que es muy útil en un nivel teórico, pero un nivel
práctico tampoco conviene obsesionarse demasiado. Es necesario tener en cuenta que todo esto
tiene que ver con límites cuando el tamaño de los problemas es muy grande y teniendo en cuenta el
peor de los casos. A efectos prácticos, si estamos seguros de que el tamaño de nuestros problemas es
pequeño, incluso un algoritmo con una complejidad "intratable" puede obtener soluciones en un
tiempo razonable.
Además, muchos algoritmos con una elevada complejidad en el peor caso, resulta que no se
comportan tan mal en la práctica, ya que muchas veces los problemas que se resuelven con él no
son el peor caso. A veces, incluso se manipulan un poco los problemas para que nunca presenten el
peor caso, o se aplican técnicas que ahorren trabajo al algoritmo (heurísticas, podas, etc). La
complejidad del algoritmo es la misma, pero en promedio se comportan mucho mejor que lo que
cabría esperar vista su complejidad en el peor caso, simplemente porque no se suele llegar al peor
caso.
Por último, comentar que existen otras medidas de complejidad que las vistas hasta aquí, que son
simplemente máximos y mínimos teóricos cuando la talla del problema tiende a un número muy
grande. Y también, cuando un algoritmo se quiere probar "en la práctica" se aplican otras técnicas,
principalmente teniendo en cuenta la probabilidad que tiene un problema en aparecer o no. Por
ejemplo, los algoritmos de ordenación de arrays más sencillos tienen una complejidad máxima

Página 11
¿QUE ES LA COMPLEJIDAD DE UN ALGORITMO?

teórica de O(n2). Uno de los peores casos que se pueden presentar es que el array esté ordenado
completamente al revés de como queremos... pero en una aplicación real es muy poco probable que
esto ocurra... con lo que a veces la realidad no es tan mala, especialmente cuando los problemas no
tienen una talla muy elevada.

Página 12

Você também pode gostar