Cuando los datos se multiplican por diez
La complejidad de un algoritmo mide cuántos pasos da cuando los datos crecen. Sirve para saber si un programa seguirá siendo rápido con diez veces más datos.
Una universidad guarda 1.000 nombres de alumnos. Buscar uno mirando la lista de principio a fin puede costar 1.000 pasos. Con 10.000 alumnos costará 10.000. Otra forma de buscar apenas notaría el cambio. Esta lección te enseña a contar y a ver la diferencia.
Al final de esta lección
Nota
Puedo contar los pasos de un algoritmo y decir cómo crece ese número.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Algoritmo | una lista de pasos que resuelve un problema | |
| Paso | una operación sencilla, como comparar o sumar | |
| Tamaño de la entrada | cuántos datos recibe el algoritmo; se escribe n | n = 1000 |
| Complejidad | cómo crece el número de pasos al crecer n | |
| Constante | los pasos no cambian aunque crezca n | |
| Lineal | los pasos crecen igual que n |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un paso es una operación sencilla
Para comparar algoritmos no medimos segundos. Contamos pasos. Un paso es una operación sencilla: comparar dos números, sumar o guardar un valor.
Contamos solo lo que se repite con los datos. Si el programa mira cada precio una vez, hay un paso por precio. Si la lista crece, el número de pasos crece con ella. Ese número depende de n, el tamaño de la entrada.
Contar los pasos de una búsqueda del máximo
# Buscar el precio más alto de una lista, contando los pasos.
prices = [12, 7, 30, 18, 25]
steps = 0
biggest = prices[0]
for price in prices:
steps = steps + 1
if price > biggest:
biggest = price
print("Precio más alto:", biggest)
print("Pasos:", steps)
# Añade cinco precios más a la lista y vuelve a ejecutar.
Cuatro formas de crecer
Un algoritmo constante da siempre los mismos pasos, como mirar el primer elemento. Uno lineal da un paso por dato. Uno cuadrático compara cada dato con todos los demás, así que da n por n pasos.
Uno logarítmico parte los datos por la mitad en cada paso. Con un millón de datos solo da 19 pasos.
Pasos según el tamaño n
| n | Constante | Logarítmico | Lineal | Cuadrático |
|---|---|---|---|---|
| 10 | 1 | 3 | 10 | 100 |
| 100 | 1 | 6 | 100 | 10.000 |
| 1.000 | 1 | 9 | 1.000 | 1.000.000 |
| 1.000.000 | 1 | 19 | 1.000.000 | 1.000.000.000.000 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Partir un millón por la mitad
python3 -c "import math; print(math.floor(math.log2(1000000)))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Los pasos cuadráticos con un millón de datos
python3 -c "print(1000000 ** 2)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error frecuente
Advertencia
Mucha gente cree que el algoritmo con menos pasos con diez datos es siempre el mejor. No: la complejidad habla de lo que pasa cuando n crece. Uno cuadrático puede ganar con diez datos y perder con diez mil.
Dos bucles anidados multiplican los pasos
Un bucle dentro de otro repite el bucle de dentro una vez por cada vuelta del de fuera. Si comparas cada línea de un registro con todas las que van después, haces n por n menos uno, entre dos, comparaciones.
Con cuatro líneas son 6. Con diez son 45. El crecimiento sigue siendo cuadrático.
Contar las comparaciones de dos bucles
# Comparar cada línea del registro con todas las que van después.
lines = ["a", "b", "c", "d"]
steps = 0
for i in range(len(lines)):
for j in range(i + 1, len(lines)):
steps = steps + 1
print("Comparaciones:", steps)
# Cambia la lista a seis líneas y mira cómo salta el número.
Por qué contamos pasos y no segundos
La orden time mide los segundos de una sola ejecución en una sola máquina. Otro ordenador, u otro momento, da otro número.
Los pasos no cambian: son los mismos en cualquier máquina. Por eso un algoritmo se compara por sus pasos. El siguiente Run imprime la suma, y después tres líneas llamadas real, user y sys, con tiempos que cambian cada vez.
Mide una ejecución con time
time python3 -c "print(sum(range(1000000)))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.