Wyszukiwanie liniowe i binarne w Javie z przykładami
Zaktualizowano 22 października 2026
Wyszukiwanie liniowe i binarne w Javie odpowiada na pytanie, które zadaje prawie każdy program: czy dana wartość jest w tablicy, a jeśli tak, to gdzie? Czy program szuka numeru klienta, czy imienia na liście, zawsze coś wyszukuje. W tym artykule poznasz dwie klasyczne metody: wyszukiwanie liniowe i binarne. Zobaczysz też, jak mierzy się, jak szybki jest algorytm.
Wyszukiwanie liniowe
Wyszukiwanie liniowe przechodzi tablicę od początku do końca i porównuje każdy element z szukaną wartością. Przy pierwszym trafieniu zwraca indeks. Jeśli dojdzie do końca i nic nie znajdzie, zwraca -1. -1 nigdy nie jest poprawnym indeksem, dlatego dobrze nadaje się jako znak „nie znaleziono”.
Wyszukiwanie liniowe działa z każdą tablicą, posortowaną czy nie, i z każdym typem. Napisy (String) porównujesz przy tym przez equals, a nie przez ==.
public class Main { public static int indexOf(int[] numbers, int target) { for (int i = 0; i < numbers.length; i++) { if (numbers[i] == target) { return i; } } return -1; }
public static void main(String[] args) { int[] numbers = {42, 7, 19, 3, 7}; System.out.println(indexOf(numbers, 7)); System.out.println(indexOf(numbers, 3)); System.out.println(indexOf(numbers, 99)); }}
Warianty łatwo zbudować: dla ostatniego trafienia pętla biegnie od tyłu, przy liczeniu przechodzi całą tablicę, a dla minimum lub maksimum zapamiętujesz indeks najlepszego dotąd elementu.
Wyszukiwanie binarne
Jeśli tablica jest posortowana rosnąco, da się to zrobić dużo szybciej. Wyszukiwanie binarne patrzy na środek przedziału:
- Jeśli wartość w środku jest równa szukanej, koniec.
- Jeśli jest mniejsza, cel może leżeć tylko na prawo od niej:
lo = mid + 1. - Jeśli jest większa, cel może leżeć tylko na lewo od niej:
hi = mid - 1.
lo i hi to granice przedziału, który jeszcze wchodzi w grę, obie włącznie. Pętla działa, dopóki przedział nie jest pusty, czyli while (lo <= hi). W każdym kroku przedział zmniejsza się o połowę.
public class Main { public static int binarySearch(int[] sorted, int target) { int lo = 0; int hi = sorted.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; System.out.println("lo=" + lo + " mid=" + mid + " hi=" + hi); if (sorted[mid] == target) { return mid; } else if (sorted[mid] < target) { lo = mid + 1; } else { hi = mid - 1; } } return -1; }
public static void main(String[] args) { int[] sorted = {3, 7, 19, 25, 42, 56, 80}; System.out.println("Found at " + binarySearch(sorted, 56)); }}
Ten sam pomysł działa też rekurencyjnie: metoda dostaje lo i hi jako parametry i wywołuje samą siebie dla odpowiedniej połowy. Warunkiem zakończenia jest lo > hi (nie znaleziono) albo trafienie w środku.
Złożoność: O(n) i O(log n)
Szybkości algorytmu nie mierzy się w sekundach, tylko tym, jak liczba kroków rośnie wraz z rozmiarem n danych wejściowych. Zapisuje się to w notacji dużego O:
- Wyszukiwanie liniowe potrzebuje w najgorszym przypadku
nporównań. Dwa razy więcej danych, dwa razy więcej kroków: O(n). - Wyszukiwanie binarne w każdym kroku dzieli przedział na pół. Po około
log₂ nkrokach zostaje tylko jeden element: O(log n).
Przy milionie elementów to milion porównań wobec około 20. W zamian tablica musi być posortowana, a samo sortowanie też kosztuje czas (więcej o tym w artykułach o prostych algorytmach sortowania i szybkich algorytmach sortowania). Jeśli szukasz tylko raz, często wystarczy wyszukiwanie liniowe. Jeśli często szukasz w tej samej tablicy, sortowanie się opłaca.
public class Main { public static int linearSteps(int[] sorted, int target) { int steps = 0; for (int value : sorted) { steps++; if (value == target) { break; } } return steps; }
public static int binarySteps(int[] sorted, int target) { int steps = 0; int lo = 0; int hi = sorted.length - 1; while (lo <= hi) { steps++; int mid = lo + (hi - lo) / 2; if (sorted[mid] == target) { break; } else if (sorted[mid] < target) { lo = mid + 1; } else { hi = mid - 1; } } return steps; }
public static void main(String[] args) { for (int n = 10; n <= 1_000_000; n *= 10) { int[] sorted = new int[n]; for (int i = 0; i < n; i++) { sorted[i] = 2 * i; } int target = sorted[n - 1]; System.out.println("n=" + n + " linear: " + linearSteps(sorted, target) + " binary: " + binarySteps(sorted, target)); } }}Wyszukiwanie z biblioteką standardową
W prawdziwych programach rzadko piszesz wyszukiwanie sam. Arrays.binarySearch szuka binarnie w posortowanej tablicy, List.indexOf i List.contains szukają liniowo w liście.
Jeśli wartości brakuje, Arrays.binarySearch nie zwraca -1, tylko -(punkt wstawienia) - 1. Punkt wstawienia to miejsce, w którym wartość musiałaby stać, żeby tablica pozostała posortowana. W przykładzie 10 należy na indeks 2, więc wynikiem jest -3.
import java.util.Arrays;import java.util.List;
public class Main { public static void main(String[] args) { int[] numbers = {42, 7, 19, 3}; Arrays.sort(numbers); System.out.println(Arrays.toString(numbers)); System.out.println(Arrays.binarySearch(numbers, 19)); System.out.println(Arrays.binarySearch(numbers, 10));
List<String> names = List.of("Ali", "Mia", "Tom"); System.out.println(names.indexOf("Mia")); System.out.println(names.contains("Eva")); }}Typowe błędy
Wyszukiwanie binarne na nieposortowanych danych
Wyszukiwanie binarne zakłada, że na lewo od
midsą tylko mniejsze wartości, a na prawo tylko większe. Jeśli tablica nie jest posortowana, nie rzuca błędu, tylko po prostu zwraca złe wyniki, na przykład-1dla wartości, która w tablicy jest. Posortuj najpierw albo użyj wyszukiwania liniowego.Pomyłka o jeden w warunku i granicach
Jeśli
loihisą obie włącznie, pętla musi mieć postaćwhile (lo <= hi). Zlo < hiostatni pozostały element nigdy nie zostanie sprawdzony i wyszukiwanie przeoczy wartości na brzegu. Równie ważne:lo = mid + 1ihi = mid - 1. Zlo = midpętla może działać w nieskończoność, bo przedział przestaje się zmniejszać.Przepełnienie w (lo + hi) / 2
Przy bardzo dużych tablicach
lo + himoże przekroczyć największą wartośćinti stać się ujemne. Wtedymidjest niepoprawnym indeksem. Bezpieczna jest wersja:int mid = lo + (hi - lo) / 2;hi - lonigdy nie jest większe niż długość tablicy, więc tu nic nie może się przepełnić. Dla małych tablic w ćwiczeniach obie wersje są poprawne, ale na egzaminie bezpieczna forma robi dobre wrażenie.
Zadania z tego tematu
Przećwicz to, czego się nauczyłeś, od razu w przeglądarce. Testy natychmiast sprawdzają twoje rozwiązanie.
- Wyszukiwanie liniowePro
- Ostatnie wystąpienie i liczba wystąpieńPro
- Pseudokod: wyszukiwanie liniowePro
- Pozycja minimum i maksimumPro
- Wyszukiwanie w tablicy 2DPro
- Wyszukiwanie binarnePro
- Co to wypisze? Wyszukiwanie binarne krok po krokuPro
- Znajdź błąd: wyszukiwanie binarnePro
- Rekurencyjne wyszukiwanie binarnePro
- Dolna granica i liczba wystąpieńPro
- Wyszukiwanie w posortowanej macierzyPro
Powiązane artykuły
- TabliceTablice w Javie w prosty sposób: tworzenie, przechodzenie pętlą, tablice dwuwymiarowe. Z przykładami i typowymi błędami, np. złym indeksem.Czytaj artykuł
- Proste sortowanieSortowanie bąbelkowe, przez wybór i przez wstawianie w Javie krok po kroku: przykłady, złożoność, stabilność i typowe błędy, których warto unikać.Czytaj artykuł
- Klasyczne algorytmyNWD algorytmem Euklidesa, sito, systemy liczbowe, algorytm Luhna i algorytm zachłanny w Javie: krótkie przykłady, złożoność i typowe błędy.Czytaj artykuł