Wyszukiwanie binarne jest to algorytm, który potrafi wyszukać w krótkim czasie żądany element. Przeszukiwana tablica musi być posortowana. Algorytm polega na zawężaniu zakresu gdzie może znajdować się szukany element. Na początku algorytm porównuje poszukiwany element z elementem pośrodku przeszukiwanego zakresu. W przypadku braku takiego elementu przyjmuje się, że porównujemy z jednym z elementów prawie po środku. Jeśli szukany element jest większy od wybranej liczby a to przeszukujemy zakres tablicy po prawej strony. W każdym kolejnym kroku zmniejszamy zakres dwa razy, aż nie natrafimy na żądany element.
Dzielenie przeszukiwanego zakresu na dwa w każdym kolejnym kroku pozwala na uzyskanie złożoność czasowej rzędu Θ(log2n). Oznacza to, że dla tablicy długości 1000 sprawdzimy maksymalnie 10 znaków, ponieważ log21000 = 9.9657... ≈ 10. Z kolei dla tablicy długości 1,000,000,000 elementów porównamy zaledwie 30 elementów! Jak widać oszczędność czasowa jest tu znacząca. Tak samo jak w przypadku wyszukiwania liniowego złożoność pamięciowa wynosi Θ(1), ponieważ będziemy potrzebowali tylko kilka dodatkowych zmiennych.
Załóżmy, że mamy posortowaną tablicę liczb całkowitych L:={1, 2, 3, 4, 5, 6, 7, 8, 9, 10}. Naszym zadaniem jest wyznaczenia pozycji liczby 7:
L | P | Lista z zakresu | Środek | Komentarz |
---|---|---|---|---|
1 | 10 | {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | 5.5 ≈ 5 | piąty element to 5, nie jest to szukana i jest mniejszy od szukanej, więc sprawdzamy zakres po prawej stronie |
6 | 10 | {6, 7, 8, 9, 10} | 8 | ósmy element to 8, nie jest to szukana i jest większa od szukanej, więc sprawdzamy zakres po lewej stronie |
6 | 7 | {6, 7} | 6.5 ≈ 6 | szósty element to 6, nie jest to szukana i jest mniejsza od szukanej, więc sprawdzamy zakres po prawej stronie |
7 | 7 | {7} | 7 | siódmy element to 7, jest to szukana, zwracamy indeks 7 |
Szukaną wartość znaleźliśmy na pozycji numer 7.
Funkcja wyszukaj() realizująca algorytm wyszukiwania binarnego przyjmuje 3 argumenty: lista - posortowana lista na której należy znaleźć element, n - ile jest elementów na liście oraz szukana - element do wyszukiwania.
(1.) Nasza funkcja wyszukaj() przyjmuje trzy argumenty: lista - tablicę zawierającą posortowane elementy. W tym przypadku jest to tablica posortowanych liczb rzeczywistych. Funkcja przyjmuje jeszcze n - długość tablicy oraz szukana - liczbę rzeczywistą, którą chcemy wyszukać. (2.) Na początek ustalamy zakres przeszukiwanego zakresu. W tym przypadku jest to [L, P] = [0, n - 1]. Deklarowane sr to środek przeszukiwanego zakresu. (3.) Dopóki L ≤ P to: (4.) obliczamy środek - jest to średnia arytmetyczna indeksu elementu pierwszego i ostatniego przeszukiwanego zakresu. (5.) Sprawdzamy czy na pozycji sr jest nasz poszukiwana liczba. Jeśli tak to (6.) zwracamy pozycję. Jeśli jednak nie to (7.) sprawdzamy czy element na pozycji sr jest większy od poszukiwanej liczby. Jeśli jest mniejszy to (8.) zmniejszamy zakres z prawej strony. W przeciwnym wypadku (10.) przesuwamy zakres z lewej strony. Jeśli wyjdziemy poza pętle while oznacza to, że w tablicy nie poszukiwanego elementu czyli (12.) zwracamy -1. Będzie to oznaczało, że dany element nie istnieje.
Na początek zadeklarujemy funkcją pomocniczą, która będzie odpowiadała za wyszukiwanie. Potem napiszemy główną funkcję wyszukaj():
(1.) Tym razem przyjmujemy cztery argumenty: lista - tablica do przeszukania, szukana - element do znalezienia, L i P - odpowiednio lewy i prawy indeks zakresu. (2.) Wyliczamy środek zakresu. (3.) Jeśli środkowy element jest równy szukanemu to (4.) zwracamy indeks sr. (5.) Jeśli L = P i nie zwróciliśmy wyniku oznacza to, że dany element nie istnieje. Wtedy (6.) zwracamy -1. (7.) Jeśli nie znaleźliśmy poszukiwanej wartości oraz L ≠ P to zmieniamy zakres wywołując funkcję z odpowiednimi parametrami i zwracając (8. - 9.) odpowiedni wynik.
Teraz nasz funkcja zbiega się tylko do jednej linijki. Jej nagłówek jest zgodny z poprzednią implementacją. Jednak (1.) tym razem zwracamy wynik funkcji wyszukaj_pom() dla zakresu [L, P] = [0, n - 1]. Warto zwrócić uwagę, że tym razem nie przekazujemy dalej wartości n. Nie ma takiej potrzeby, ponieważ nie wyjdziemy poza zakres w funkcji wyszukaj_pom(), dzięki ustaleniu wartości L i P.
Obydwie funkcje możemy przetestować używając poniższej funkcji main().