Menu
Coddy logo textTech

Wyszukiwanie binarne (binary search)

Ostatnia aktualizacja

Wyszukiwanie binarne znajduje szukaną wartość w **posortowanej** tablicy, wielokrotnie dzieląc okno wyszukiwania na pół. Porównuje środkowy element z celem: trafienie kończy wyszukiwanie, a w przeciwnym razie połowa, w której cel nie może się znajdować, zostaje odrzucona i okno zawęża się do drugiej połowy. Każde porównanie eliminuje połowę pozostałych elementów, dlatego algorytm działa w O(log n): przeszukanie miliona posortowanych wartości wymaga najwyżej około 20 porównań.

Animacja powyżej pokazuje wskaźniki lo, mid i hi oraz przyciemnia odrzuconą połowę po każdym porównaniu. Jeden warunek jest nienegocjowalny: tablica musi być już posortowana. Dla nieposortowanych danych potrzebujesz wyszukiwania liniowego albo najpierw sortowania (zobacz merge sort). Ta sama idea dzielenia na pół napędza binarne drzewo poszukiwań.

Złożoność czasowa i pamięciowa

PrzypadekZłożonośćUwagi
Najlepszy przypadekO(1)Środkowy element jest celem już przy pierwszym porównaniu.
Średni przypadekO(log n)Każde porównanie zmniejsza pozostałe okno o połowę.
Najgorszy przypadekO(log n)Okno kurczy się do jednego elementu, zanim nastąpi trafienie lub pudło.
PamięćO(1)Wersja iteracyjna przechowuje tylko indeksy lo, hi i mid.

Krok po kroku

KrokCo się dzieje
1Ustaw lo na pierwszy indeks, a hi na ostatni indeks posortowanej tablicy.
2Oblicz środkowy indeks: mid = (lo + hi) // 2.
3Jeśli a[mid] jest równe celowi, zwróć mid (znaleziono).
4Jeśli a[mid] jest **mniejsze** od celu, cel może być tylko w prawej połowie: ustaw lo = mid + 1.
5Jeśli a[mid] jest **większe** od celu, szukaj w lewej połowie: ustaw hi = mid - 1.
6Powtarzaj od kroku 2, dopóki lo <= hi; jeśli okno się opróżni, celu nie ma w tablicy.

Przykład krok po kroku

Szukanie 5 w [1, 2, 3, 5, 7, 8, 9]:

PrzebiegOkno (lo..hi)mida[mid]Działanie
1[1, 2, 3, 5, 7, 8, 9] (0..6)35a[3] = 5: cel znaleziony pod indeksem 3.

Nieudane wyszukiwanie krok po kroku

Szukanie 4 w tej samej tablicy pokazuje, jak okno się opróżnia:

PrzebiegOkno (lo..hi)mida[mid]Działanie
10..6355 > 4: szukaj w lewej połowie, hi = 2.
20..2122 < 4: szukaj w prawej połowie, lo = 2.
32..2233 < 4, więc lo przyjmuje wartość 3 i okno się opróżnia: nie znaleziono.

Kiedy używać wyszukiwania binarnego

Używaj, gdyUnikaj, gdy
Dane są już posortowane (albo przeszukujesz je wiele razy)Dane są nieposortowane i przeszukujesz je tylko raz (wcześniejsze sortowanie kosztuje O(n log n))
Kolekcja obsługuje szybki dostęp swobodny (tablice)Masz tylko dostęp sekwencyjny (listy jednokierunkowe)
Zbiór danych jest duży (O(log n) błyszczy przy dużej skali)Zbiór danych jest malutki (proste przejrzenie jest równie szybkie i prostsze)

Binary Search: kod

Przejrzysta, gotowa do uruchomienia implementacja algorytmu Binary Search w językach: Python, JavaScript, Java, C++, C, Pseudocode. Wybierz język, skopiuj kod albo otwórz go od razu w edytorze online Coddy.

Binary Search: kod (Python)

Python
1def binary_search(a, target):2    lo, hi = 0, len(a) - 13    while lo <= hi:4        mid = (lo + hi) // 25        if a[mid] == target:6            return mid7        if a[mid] < target:8            lo = mid + 1  # search the right half9        else:10            hi = mid - 1  # search the left half11    return -112
13
14nums = [1, 2, 3, 5, 7, 8, 9]  # must be sorted15print("Index of 5:", binary_search(nums, 5))16print("Index of 4:", binary_search(nums, 4))
Uruchom ten kod w edytorze Python online

Wyszukiwanie binarne: najczęstsze pytania

Jaka jest złożoność czasowa wyszukiwania binarnego?
O(log n) w średnim i najgorszym przypadku, bo każde porównanie zmniejsza pozostałe okno wyszukiwania o połowę, oraz O(1) w najlepszym przypadku, gdy pierwszy środkowy element jest celem. Wersja iteracyjna używa O(1) dodatkowej pamięci.
Dlaczego wyszukiwanie binarne wymaga posortowanej tablicy?
Krok dzielenia na pół opiera się na porządku: porównanie celu ze środkowym elementem mówi, którą połowę odrzucić, tylko wtedy, gdy wszystko na lewo od środka jest mniejsze, a wszystko na prawo większe. Dla nieposortowanych danych ten wniosek jest nieprawdziwy, więc użyj wyszukiwania liniowego albo najpierw posortuj dane.
Czym różni się wyszukiwanie binarne od wyszukiwania liniowego?
Wyszukiwanie liniowe przegląda elementy po kolei (O(n)) i działa na dowolnej tablicy; wyszukiwanie binarne dzieli na pół okno wyszukiwania posortowanej tablicy (O(log n)), ale wymaga posortowanych danych. Przy kilku elementach różnica jest pomijalna; przy dużej skali wyszukiwanie binarne zdecydowanie wygrywa.
Ile porównań potrzebuje wyszukiwanie binarne?
Najwyżej około log2(n) + 1: 10 porównań wystarcza na 1000 elementów, 20 porównań na 1 000 000. Ten logarytmiczny wzrost sprawia, że jest to domyślna metoda wyszukiwania w posortowanych danych.
Na czym polega klasyczny błąd przepełnienia w wyszukiwaniu binarnym?
Obliczanie środka jako (lo + hi) / 2 może przepełnić liczby całkowite o stałym rozmiarze, gdy lo + hi przekroczy maksimum typu. Bezpieczna forma to mid = lo + (hi - lo) / 2. W Pythonie nie ma to znaczenia (liczby całkowite o dowolnej precyzji), ale w Javie, C i C++ to prawdziwy, słynny błąd.
Czy wyszukiwanie binarne to to samo co binarne drzewo poszukiwań?
Łączy je idea dzielenia na pół, ale różnią się strukturą: wyszukiwanie binarne to algorytm działający na posortowanej tablicy, a binarne drzewo poszukiwań to połączona struktura danych, która utrzymuje klucze w porządku, dzięki czemu wyszukiwanie w każdym węźle schodzi w lewo lub w prawo.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ