Necesito un algoritmo de búsqueda binaria que sea compatible con los contenedores C ++ STL, algo así como std::binary_search
en el <algorithm>
encabezado de la biblioteca estándar , pero lo necesito para devolver el iterador que apunta al resultado, no un simple booleano que me diga si el elemento existe.
(En una nota al margen, ¿qué diablos estaba pensando el comité estándar cuando definieron la API para binary_search?)
Mi principal preocupación aquí es que necesito la velocidad de una búsqueda binaria, por lo que, aunque puedo encontrar los datos con otros algoritmos, como se menciona a continuación, quiero aprovechar el hecho de que mis datos están ordenados para obtener los beneficios de un binario. búsqueda, no una búsqueda lineal.
hasta ahora lower_bound
y upper_bound
fallar si falta el dato:
//lousy pseudo code
vector(1,2,3,4,6,7,8,9,0) //notice no 5
iter = lower_bound_or_upper_bound(start,end,5)
iter != 5 && iter !=end //not returning end as usual, instead it'll return 4 or 6
Nota: también estoy bien usando un algoritmo que no pertenece al espacio de nombres estándar siempre que sea compatible con los contenedores. Como, por ejemplo, boost::binary_search
.
fuente
Respuestas:
No existen tales funciones, pero puede escribir una simple usando
std::lower_bound
,std::upper_bound
ostd::equal_range
.Una implementación simple podría ser
Otra solución sería utilizar a
std::set
, que garantiza el orden de los elementos y proporciona un métodoiterator find(T key)
que devuelve un iterador al elemento dado. Sin embargo, es posible que sus requisitos no sean compatibles con el uso de un conjunto (por ejemplo, si necesita almacenar el mismo elemento varias veces).fuente
*i == val
! Más bien use!(val < *i)
. La razón es quelower_bound
utiliza<
, no==
(T
es decir, ni siquiera se requiere que sea comparable en igualdad). (Consulte el STL efectivo de Scott Meyers para obtener una explicación de la diferencia entre igualdad y equivalencia .)end
. Los rangos en la biblioteca estándar de C ++ se representan con intervalos semiabiertos: el iterador final "apunta" después del último elemento. Como tal, puede ser devuelto por algoritmos para indicar que no se encontró ningún valor.Deberías echarle un vistazo
std::equal_range
. Devolverá un par de iteradores al rango de todos los resultados.fuente
Hay un conjunto de ellos:
http://www.sgi.com/tech/stl/table_of_contents.html
Buscar:
En una nota aparte:
Probablemente pensaban que la búsqueda de contenedores podría dar lugar a más de un resultado. Pero en las raras ocasiones en las que solo necesita probar la existencia, una versión optimizada también sería buena.
fuente
Si std :: lower_bound es de un nivel demasiado bajo para su gusto, es posible que desee verificar boost :: container :: flat_multiset . Es un reemplazo directo para std :: multiset implementado como un vector ordenado usando búsqueda binaria.
fuente
La implementación más corta, preguntándose por qué no está incluida en la biblioteca estándar:
De https://en.cppreference.com/w/cpp/algorithm/lower_bound
fuente
Marque esta función, qBinaryFind :
La función está incluida en el
<QtAlgorithms>
encabezado, que es parte de la biblioteca Qt .fuente
std :: lower_bound () :)
fuente
Ejemplo: Considere una matriz, A = [1,2,3,4,5,6,7,8,9] Suponga que desea buscar el índice de 3 Inicialmente, inicio = 0 y final = 9-1 = 8 Ahora , desde inicio <= final; mid = 4; (matriz [mid] que es 5)! = 3 Ahora, 3 se encuentra a la izquierda de mid ya que es menor que 5. Por lo tanto, solo buscamos en la parte izquierda de la matriz. Por lo tanto, ahora start = 0 y end = 3; mid = 2.Desde array [mid] == 3, obtuvimos el número que estábamos buscando. Por lo tanto, devolvemos su índice que es igual a mid.
fuente
Una solución que devuelva la posición dentro del rango podría ser así, usando solo operaciones en iteradores (debería funcionar incluso si el iterador no es aritmético):
fuente