Potrzebuję binarnego algorytmu wyszukiwania, który jest kompatybilny z kontenerami C ++ STL, coś std::binary_search
w rodzaju <algorithm>
nagłówka biblioteki standardowej , ale potrzebuję go do zwrócenia iteratora wskazującego na wynik, a nie prostej wartości logicznej informującej mnie, czy element istnieje.
(Na marginesie, o czym myślała do cholery standardowa komisja, definiując API dla binary_search ?!)
Moim głównym zmartwieniem jest to, że potrzebuję szybkości wyszukiwania binarnego, więc chociaż mogę znaleźć dane za pomocą innych algorytmów, jak wspomniano poniżej, chcę wykorzystać fakt, że moje dane są sortowane, aby uzyskać korzyści z binarnego wyszukiwanie, a nie wyszukiwanie liniowe.
do tej pory lower_bound
i upper_bound
niepowodzenie, jeśli brakuje odniesienia:
//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
Uwaga: mogę również używać algorytmu, który nie należy do przestrzeni nazw std, o ile jest zgodny z kontenerami. Powiedzmy boost::binary_search
.
źródło
Odpowiedzi:
Nie ma takich funkcji, ale prostą można napisać za pomocą
std::lower_bound
,std::upper_bound
lubstd::equal_range
.Może to być prosta implementacja
Innym rozwiązaniem byłoby użycie pliku
std::set
, który gwarantuje kolejność elementów i dostarcza metodęiterator find(T key)
zwracającą iterator do danego elementu. Jednak Twoje wymagania mogą nie być zgodne z wykorzystaniem zestawu (na przykład, jeśli musisz wielokrotnie przechowywać ten sam element).źródło
*i == val
! Raczej używaj!(val < *i)
. Powodem jest to, żelower_bound
używa<
, a nie==
(tj.T
Nie jest nawet wymagane, aby były porównywalne z równością). (Zobacz Efektywne STL Scotta Meyersa, aby uzyskać wyjaśnienie różnicy między równością a równoważnością ).end
. Zakresy w bibliotece standardowej C ++ są reprezentowane w półotwartych odstępach: iterator końcowy „wskazuje” po ostatnim elemencie. W związku z tym może zostać zwrócony przez algorytmy, aby wskazać, że nie znaleziono żadnej wartości.Powinieneś rzucić okiem
std::equal_range
. Zwróci parę iteratorów do zakresu wszystkich wyników.źródło
Jest ich zestaw:
http://www.sgi.com/tech/stl/table_of_contents.html
Szukaj:
W osobnej notatce:
Prawdopodobnie myśleli, że wyszukiwanie kontenerów może dać więcej niż jeden wynik. Ale w dziwnych przypadkach, gdy wystarczy przetestować istnienie zoptymalizowanej wersji, również byłaby miła.
źródło
Jeśli std :: lower_bound jest zbyt niski dla twoich upodobań, możesz sprawdzić boost :: container :: flat_multiset . Jest to zamiennik typu drop-in dla std :: multiset zaimplementowany jako posortowany wektor przy użyciu wyszukiwania binarnego.
źródło
Najkrótsza implementacja, zastanawiasz się, dlaczego nie ma jej w standardowej bibliotece:
Od https://en.cppreference.com/w/cpp/algorithm/lower_bound
źródło
Sprawdź tę funkcję, qBinaryFind :
Funkcja jest zawarta w
<QtAlgorithms>
nagłówku, który jest częścią biblioteki Qt .źródło
std :: lower_bound () :)
źródło
Przykład: Rozważ tablicę, A = [1,2,3,4,5,6,7,8,9] Załóżmy, że chcesz przeszukać indeks 3 Początkowo, start = 0 i end = 9-1 = 8 Teraz , od początku <= koniec; mid = 4; (tablica [mid], która wynosi 5)! = 3 Teraz 3 leży na lewo od środka, ponieważ jest mniejsze niż 5. Dlatego przeszukujemy tylko lewą część tablicy. Stąd start = 0 i end = 3; mid = 2. Ponieważ array [mid] == 3, otrzymaliśmy liczbę, której szukaliśmy. Dlatego zwracamy jego indeks równy połowie.
źródło
Rozwiązanie zwracające pozycję wewnątrz zakresu mogłoby wyglądać następująco, używając tylko operacji na iteratorach (powinno działać nawet jeśli iterator nie wykonuje arytmetyki):
źródło