2.3. Notación O-grande¶
Al tratar de caracterizar la eficiencia de un algoritmo en términos del tiempo de ejecución, independientemente de cualquier programa o computadora en particular, es importante cuantificar el número de operaciones o pasos que el algoritmo requerirá. Si se considera que cada uno de estos pasos es una unidad básica de cálculo, entonces el tiempo de ejecución de un algoritmo puede expresarse como el número de pasos necesarios para resolver el problema. Decidir sobre una unidad básica de cálculo apropiada puede ser un problema complicado y dependerá de cómo se implemente el algoritmo.
Una buena unidad básica de cálculo para comparar los algoritmos de sumatoria mostrados anteriormente podría ser contar el número de instrucciones de asignación realizadas para calcular la suma. En la función sumaDeN
, el número de instrucciones de asignación es 1 (
En las funciones de sumatoria mencionadas anteriormente, tiene sentido utilizar el número de términos en la sumatoria para indicar el tamaño del problema. Podemos decir entonces que la suma de los primeros 100,000 enteros es un caso más grande del problema de la suma que la suma de los primeros 1,000. Debido a esto, podría parecer razonable que el tiempo requerido para resolver el caso más grande fuera mayor que para el caso más pequeño. Nuestro objetivo entonces es mostrar cómo cambia el tiempo de ejecución del algoritmo con respecto al tamaño del problema.
Los científicos de la computación prefieren llevar esta técnica de análisis un poco más allá. Resulta que el número exacto de operaciones no es tan importante como determinar la parte más dominante de la función
En el ejemplo anterior,
Como ejemplo alternativo, supongamos que para algún algoritmo, el número exacto de pasos es
Aunque no vemos esto en el ejemplo de la suma, a veces el rendimiento de un algoritmo depende de los valores exactos de los datos en lugar de simplemente el tamaño del problema. Para este tipo de algoritmos necesitamos caracterizar su desempeño en términos del mejor caso, el peor caso, o el caso promedio. El peor caso de rendimiento se refiere a un conjunto de datos en particular, donde el algoritmo se comporta especialmente mal. Mientras que un conjunto de datos diferente para el mismo algoritmo podría tener un rendimiento extraordinariamente bueno. Sin embargo, en la mayoría de los casos, el algoritmo se comporta de algún modo entre estos dos extremos (caso promedio). Es importante que un científico de la computación entienda estas distinciones para que no resulten engañosas en un caso particular.
Una serie de funciones de orden de magnitud muy comunes aparecerán una y otra vez a medida que usted estudia algoritmos. Éstas se muestran en la Tabla 1. Para decidir cuál de estas funciones es la parte dominante de cualquier función
f(n) |
Nombre |
---|---|
Constante |
|
Logarítmica |
|
Lineal |
|
Log-lineal |
|
Cuadrática |
|
Cúbica |
|
Exponencial |
La Figura 1 muestra las gráficas de las funciones comunes de la Tabla 1. Note que cuando n es pequeño, las funciones no están muy bien definidas una con respecto a otra. Es difícil saber cuál es la dominante. Sin embargo, a medida que n crece, existe una relación definida y es fácil compararlas entre sí.

Figura 1: Gráficas de las funciones comunes para la notación O-grande¶
Figura 1: Gráficas de las funciones comunes para la notación O-grande
Como ejemplo final, supongamos que tenemos el fragmento de código en Python que se muestra en el Programa 2. Aunque este programa realmente no hace nada, es instructivo ver cómo podemos considerar el código real y analizar su rendimiento.
Programa 2
a=5
b=6
c=10
for i in range(n):
for j in range(n):
x = i * i
y = j * j
z = i * j
for k in range(n):
w = a*k + 45
v = b*b
d = 33
El número de operaciones de asignación es la suma de cuatro términos. El primer término es la constante 3, que representa las tres instrucciones de asignación al inicio del fragmento de código. El segundo término es

Figura 2: Comparación de
Figura 2: Comparación de
La Figura 2 muestra algunas de las funciones comunes para la notación O-grande comparadas con la función
Autoevaluación
Escriba dos funciones en Python para encontrar el número mínimo en una lista. La primera función debe comparar cada número de una lista con todos los demás de la lista.