¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Búsqueda lineal y búsqueda binaria

Después de esta lección: Puedo encontrar un dato con la búsqueda lineal y con la búsqueda binaria.

Lección de 45 min4 comandosLaboratorio JupyterLab de ciencia de datos: pandas, Matplotlib y scikit-learn en el navegador

Encontrar un día entre 365

Una búsqueda es encontrar un dato dentro de una lista, como un nombre en tu agenda. Con la búsqueda lineal y la búsqueda binaria encuentras un dato mirando muy pocos elementos.

Piensa en la lista de bicicletas alquiladas cada día de un año: 365 números. Buscas un día concreto. ¿Cuántos tienes que mirar?

Al final de esta lección

Nota

Puedo encontrar un dato con la búsqueda lineal y con la búsqueda binaria.

Palabras clave

PalabraQué significaEjemplo
Algoritmouna lista de pasos que resuelve un problema
Búsqueda linealmirar los elementos uno por uno desde el principio
Búsqueda binariamirar el elemento del medio y descartar la mitad
Lista ordenadauna lista con los valores de menor a mayor
Comparaciónmirar un elemento para saber si es el que buscas
Índicela posición de un elemento en una lista, que empieza en 00

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

La búsqueda lineal mira todos los elementos

Imagina que buscas tu nombre en una lista de clase sin ordenar. Empiezas por el primero y sigues hasta encontrarlo.

Eso es la búsqueda lineal. Funciona con cualquier lista, ordenada o no. En el peor caso, el dato está el último o no está, y miras los 365 elementos.

La búsqueda lineal en Python

Código: python
# Devuelve el índice del dato, o -1 si no está.
def linear_search(items, target):
    for index in range(len(items)):
        if items[index] == target:
            return index
    return -1

hires = [137, 212, 173, 327, 204, 98, 251]
print(linear_search(hires, 327))
print(linear_search(hires, 500))

Carga los 365 días del laboratorio

Comando
docker exec jupyter python3 -c "import csv; h=[int(r['hires']) for r in csv.DictReader(open('hires.csv'))]; print(len(h), h[:5])"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Busca el día con más alquileres

Comando
docker exec jupyter python3 -c "import csv; h=[int(r['hires']) for r in csv.DictReader(open('hires.csv'))]; print(max(h), h.index(max(h)) + 1)"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Cuántas comparaciones hizo la búsqueda

El primer Run imprime 365 [137, 212, 173, 327, 204]: hay 365 días y estos son los cinco primeros.

El segundo imprime 487 173. El máximo, 487 alquileres, está en el índice 172. La búsqueda lineal necesitó 173 comparaciones para llegar hasta él.

La búsqueda binaria descarta la mitad cada vez

Si la lista está ordenada, hay un atajo. Miras el elemento del medio.

Si es menor que el dato, todo lo de su izquierda es menor también, así que lo descartas. Si es mayor, descartas la derecha. Repites con la mitad que queda.

Es como adivinar un número del 1 al 100 cuando te dicen "más alto" o "más bajo".

Ejemplo resuelto: buscar el 58 en nueve números

PasoZona que quedaElemento del medioQué haces
1Índices 0 a 831 (índice 4)31 es menor que 58: te quedas con la derecha
2Índices 5 a 847 (índice 6)47 es menor que 58: te quedas con la derecha
3Índices 7 a 858 (índice 7)Es el dato: has terminado

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

La búsqueda binaria cuenta sus pasos

Código: python
# La lista tiene que estar ordenada.
def binary_search(items, target):
    low = 0
    high = len(items) - 1
    steps = 0
    while low <= high:
        middle = (low + high) // 2
        steps = steps + 1
        if items[middle] == target:
            return middle, steps
        if items[middle] < target:
            low = middle + 1
        else:
            high = middle - 1
    return -1, steps

ordered = [5, 12, 18, 25, 31, 40, 47, 58, 66]
print(binary_search(ordered, 58))
print(binary_search(ordered, 20))

Un error frecuente

Advertencia

Mucha gente cree que la búsqueda binaria funciona con cualquier lista. Solo funciona si la lista está ordenada. Con una lista desordenada, descartar la mitad puede tirar justo el dato que buscas.

Comprueba si la lista del laboratorio está ordenada

Comando
docker exec jupyter python3 -c "import csv; h=[int(r['hires']) for r in csv.DictReader(open('hires.csv'))]; print(h == sorted(h), sorted(h)[:5])"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

La lista de alquileres no está ordenada

El Run imprime False [41, 61, 79, 94, 101]. Los alquileres están en el orden de los días, no de menor a mayor, y los cinco más bajos de todo el año son esos.

Para usar la búsqueda binaria aquí, primero hay que ordenar la lista. Ordenar tiene su propio coste, y lo verás en la próxima lección.

Cuántos pasos hace la búsqueda binaria

Cada paso deja la mitad de los elementos. Con 16 elementos quedan 8, luego 4, luego 2 y luego 1. Son 5 pasos como máximo.

Una lista diez veces más larga no necesita diez veces más pasos. Solo necesita unos pocos más.

Cuenta los pasos máximos para 365 días

Comando
docker exec jupyter python3 -c "import csv; h=[int(r['hires']) for r in csv.DictReader(open('hires.csv'))]; print(len(h).bit_length())"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Por qué sale 9

El Run imprime 9. El número 365 se escribe con nueve cifras en binario, y ese es justo el máximo de pasos de la búsqueda binaria.

Mira la tabla: la búsqueda lineal crece con la lista, y la binaria casi no cambia.

Ejemplo resuelto: pasos máximos según el tamaño

ElementosPasos de la búsqueda linealPasos de la búsqueda binaria
15154
3653659
1000100010
1000000100000020

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Para ir más lejos: compara tú los tiempos

En el cuaderno, ordena la lista con sorted y busca un valor con tu función. Después prueba %timeit con la búsqueda lineal y con bisect_left del módulo bisect.

Apunta lo que ves. El tiempo cambia de una máquina a otra y de una vez a otra. Los pasos no cambian nunca: por eso los contamos.

Sobre este laboratorio y su código: Laboratorio JupyterLab de ciencia de datos: pandas, Matplotlib y scikit-learn en el navegador

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.