Bienvenidos
En este artículo, aprenderá cómo funciona el algoritmo de búsqueda binaria entre bastidores y cómo puede implementarlo en Python.
En particular, aprenderá:
- Cómo funciona el algoritmo detrás de escena para encontrar un elemento objetivo.
- Cómo funciona su implementación de Python línea por línea.
- Por qué es un algoritmo muy eficiente en comparación con la búsqueda lineal.
- Sus ventajas y requisitos.
¡Vamos a empezar! ✨
? Introducción a la búsqueda binaria
Este algoritmo se utiliza para encontrar un elemento en una secuencia ordenada (por ejemplo: una lista, tupla o cadena).
Requisitos
Para aplicar el algoritmo de búsqueda binaria a una secuencia, la secuencia ya debe estar ordenada en orden ascendente. De lo contrario, el algoritmo no encontrará la respuesta correcta. Si lo hace, será por pura coincidencia.
? Sugerencia: puede ordenar la secuencia antes de aplicar la búsqueda binaria con un algoritmo de ordenación que satisfaga sus necesidades.
Entrada y salida
El algoritmo (implementado como una función) necesita estos datos:
- Una secuencia ordenada de elementos (por ejemplo: lista, tupla, cadena).
- El elemento de destino que estamos buscando.
Devuelve el índice del elemento que está buscando si se encuentra. Si no se encuentra el elemento, se devuelve -1.
Eficiencia
Es muy eficiente en comparación con la búsqueda lineal (buscar un elemento uno por uno, comenzando desde el primero) porque podemos "descartar" la mitad de la lista en cada paso.
Empecemos a sumergirnos en este algoritmo.
? Tutorial visual
Aplicaremos el algoritmo de búsqueda binaria a esta lista:

? Sugerencia: observe que la lista ya está ordenada. Incluía los índices como referencia visual.
Objetivo
Queremos encontrar el índice del entero 67 .
Intervalo
Supongamos que somos el algoritmo. ¿Cómo iniciamos el proceso?
Empezamos seleccionando los dos límites del intervalo donde queremos buscar. Queremos buscar en toda la lista, por lo que seleccionamos índice 0
como límite inferior e índice 5
como límite superior:

Elemento medio
Ahora necesitamos encontrar el índice del elemento medio en este intervalo. Hacemos esto sumando el límite inferior y el límite superior y dividiendo el resultado por 2 usando la división de enteros.
En este caso, (0 + 5)//2
se 2
debe a que el resultado de 5/2
es 2.5
y la división entera trunca la parte decimal.
Entonces, el elemento del medio está ubicado en el índice 2 , y el elemento del medio es el número 6 :

Comparaciones
Ahora debemos comenzar a comparar el elemento intermedio con nuestro elemento objetivo para ver qué debemos hacer a continuación.
Le pedimos:
¿El elemento del medio es igual al elemento que estamos buscando?
6 == 67 # False
No, no lo es.
Entonces preguntamos:
¿El elemento del medio es mayor que el elemento que buscamos?
6 > 67 # False
No, no lo es.
Entonces, el elemento del medio es más pequeño que el elemento que estamos buscando.
6 < 67 # True
Descartar elementos
Dado que la lista ya está ordenada, esto nos dice algo extremadamente importante. Nos dice que podemos "descartar" la mitad inferior de la lista porque sabemos que todos los elementos que vienen antes del elemento del medio serán más pequeños que el elemento que estamos buscando, por lo que nuestro elemento de destino no está allí.

Empezar de nuevo: elegir los límites
¿Qué hacemos a continuación? Hemos descartado los elementos y el ciclo se repite nuevamente.
Tenemos que elegir los límites para el nuevo intervalo (ver más abajo). Pero observe que el límite superior se mantiene intacto y solo se cambia el límite inferior.

Esto se debe a que el elemento que estamos buscando podría estar en la mitad superior de la lista. El límite superior se mantiene intacto y el límite inferior se cambia para "reducir" el intervalo a un intervalo en el que podría encontrarse nuestro elemento de destino.
? Sugerencia: Si el elemento del medio hubiera sido mayor que el elemento que buscamos, el límite superior se habría cambiado y el límite inferior se habría mantenido intacto. De esta manera, descartaríamos la mitad superior de la lista y seguiríamos buscando en la mitad inferior.
Elemento medio
Ahora necesitamos encontrar el índice del elemento del medio agregando el límite inferior al límite superior y dividiendo el resultado por 2 usando la división entera.
El resultado de (3+5)//2
es 4
, por lo que el elemento del medio está ubicado en el índice4
y el elemento del medio es 67 .

Comparaciones
Le pedimos:
¿El elemento del medio es igual al elemento que estamos buscando?
67 == 67 # True
¡Sí lo es! Entonces hemos encontrado el elemento en el índice 4 . Se devuelve el valor 4 y el algoritmo se completó correctamente.
? Sugerencia: Si no se hubiera encontrado el elemento, el proceso habría continuado hasta que el intervalo ya no fuera válido. Si el elemento no se hubiera encontrado en toda la lista, se habría devuelto -1.
? Tutorial de código
Ahora que tiene una intuición visual de cómo funciona el algoritmo detrás de escena, profundicemos en la implementación iterativa de Python analizándola línea por línea:
def binary_search(data, elem): low = 0 high = len(data) - 1 while low elem: high = middle - 1 else: low = middle + 1 return -1
Encabezamiento
Aquí tenemos el encabezado de la función:
def binary_search(data, elem):
Se necesitan dos argumentos:
- La secuencia ordenada de elementos (por ejemplo: lista, tupla o cadena).
- El elemento que queremos encontrar.
Intervalo inicial
La siguiente línea establece los límites inicial inferior y superior:
low = 0 high = len(data) - 1
El límite inferior inicial es el índice 0
y el límite superior inicial es el último índice de la secuencia.
Lazo
Repetiremos el proceso mientras haya un intervalo válido, mientras que el límite inferior sea menor o igual que el límite superior.
while low <= high:
? Consejo: recuerde que los límites son índices.
Elemento medio
En cada iteración, necesitamos encontrar el índice del elemento del medio. Para hacer esto, sumamos los límites inferior y superior y dividimos el resultado por 2 usando la división de enteros.
middle = (low + high)//2
? Consejo: utilizamos la división de enteros en caso de que la lista o el intervalo contenga un número par de elementos. Por ejemplo, si la lista tuviera 6 elementos y no usáramos división entera, middle
sería el resultado de (0 + 5)/2
cuál es 2.5
. Un índice no puede ser un flotante, por lo que truncamos la parte decimal usando //
y seleccionamos el elemento en el índice 2
.
Comparaciones
Con estos condicionales (ver más abajo), determinamos qué hacer dependiendo del valor del elemento intermedio data[middle]
. Lo comparamos con el elemento objetivo que estamos buscando.
if data[middle] == elem: return middle elif data[middle] > elem: high = middle - 1 else: low = middle + 1
Hay tres opciones:
- Si el elemento del medio es igual al elemento que estamos buscando, devolvemos el índice inmediatamente porque encontramos el elemento.
if data[middle] == elem: return middle
- Si el elemento del medio es mayor que el elemento que estamos buscando, reasignamos el límite superior porque sabemos que el elemento de destino está en la mitad inferior de la lista.
elif data[middle] > elem: high = middle - 1
- De lo contrario, la única opción que queda es que el elemento del medio es más pequeño que el elemento que estamos buscando, por lo que reasignamos el límite inferior porque sabemos que el elemento de destino está en la mitad superior de la lista.
else: low = middle + 1
Elemento no encontrado
Si el ciclo se completa sin encontrar el elemento, se devuelve el valor -1.
return -1
y tenemos la implementación final del algoritmo de búsqueda binaria:
def binary_search(data, elem): low = 0 high = len(data) - 1 while low elem: high = middle - 1 else: low = middle + 1 return -1
? Casos especiales
Estos son algunos casos particulares que puede encontrar al comenzar a trabajar con este algoritmo:
Elementos repetidos
Si el elemento que está buscando se repite en la secuencia, el índice devuelto dependerá del número de elementos y de la secuencia de operaciones que el algoritmo realice en la secuencia.
>>> >>> b = [2, 2, 3, 6, 7, 7] >>> binary_search(b, 7) 4
Elemento no encontrado
Si no se encuentra el elemento, se devuelve -1.
>>> b = [2, 2, 3, 6, 7, 7] >>> binary_search(b, 8) -1
Secuencia vacía
Si la secuencia está vacía, se devolverá -1.
>>> b = [] >>> binary_search(b, 8) -1
Secuencia sin clasificar
Si la secuencia no está ordenada, la respuesta no será correcta. Obtener el índice correcto es pura coincidencia y podría deberse al orden de los elementos en la secuencia y la secuencia de operaciones realizadas por el algoritmo.
Este ejemplo devuelve el resultado correcto:
>>> b = [5, 7, 3, 0, -9, 2, 6] >>> binary_search(b, 6) 6
Pero este no:
>>> b = [5, 7, 3, 0, -9, 2, 10, 6] >>> binary_search(b, 6) -1
? Consejo: Piense por qué el primer ejemplo devuelve el resultado correcto. Sugerencia: es pura coincidencia que el orden de los elementos haga que el algoritmo alcance el índice correcto, pero el proceso paso a paso evalúa 0
, luego 2
y finalmente 6
. En este caso particular, para este elemento en particular, se encuentra el índice correcto incluso si la secuencia no está ordenada.
? Un ejemplo más complejo
Ahora que está más familiarizado con el algoritmo y su implementación de Python, aquí tenemos un ejemplo más complejo:
Queremos encontrar el índice del elemento 45 en esta lista usando la búsqueda binaria:

Primera iteración
Se seleccionan los límites inferior y superior:

Se selecciona el elemento intermedio ( 26 ):

Pero el elemento del medio ( 26 ) no es el elemento que buscamos, es menor que 45 :

Segunda iteración
Entonces podemos descartar todos los elementos que son más pequeños que el elemento del medio y seleccionar nuevos límites. El nuevo límite inferior ( 27 ) es el elemento ubicado inmediatamente a la derecha del elemento intermedio anterior:

? Consejo: recuerde que la lista ya está ordenada.
Se selecciona el nuevo elemento intermedio ( 30 ):

El elemento del medio ( 30 ) no es el elemento que buscamos, es menor que 45 :

Tercera iteración
Podemos descartar los elementos que sean menores o iguales a 30 que aún no se hayan descartado. El límite inferior se actualiza a 32 :

Aquí tenemos un caso interesante: el elemento del medio es uno de los límites del intervalo actual porque (7+8)//2
es 7
.

El elemento del medio ( 32 ) no es el elemento que buscamos ( 45 ), es más pequeño.

Cuarta iteración
Podemos descartar los elementos que sean menores o iguales a 32 que no se hayan descartado ya.
Aquí tenemos otro caso muy interesante: el intervalo solo tiene un elemento.

? Sugerencia: Este intervalo es válido porque escribimos esta condición while high <= low:
, que incluye intervalos donde el índice del límite inferior es igual al índice del límite superior.
El elemento del medio es el único elemento en el intervalo porque (8+8)//2
es 8
, por lo que el índice del elemento del medio es 8 y el elemento del medio es 45 .

Ahora el elemento del medio es el elemento que estamos buscando, 45 :

Entonces se devuelve el valor 8 (el índice):
>>> binary_search([1, 3, 7, 15, 26, 27, 30, 32, 45], 45) 8
? Práctica adicional
Si desea practicar más con este algoritmo, intente explicar cómo funciona el algoritmo entre bastidores cuando se aplica a esta lista para encontrar el entero 90 :
[5, 8, 15, 26, 38, 56]
- ¿Qué pasa paso a paso?
- ¿Qué valor se devuelve?
- ¿Se encuentra el elemento?
Realmente espero que les haya gustado mi artículo y les haya resultado útil. Ahora puede implementar el algoritmo de búsqueda binaria en Python. Consulte mi curso en línea "Algoritmos de búsqueda y clasificación de Python: un enfoque práctico". Sigueme en Twitter. ⭐️