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 n poró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₂ n krokach 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 mid są 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 -1 dla wartości, która w tablicy jest. Posortuj najpierw albo użyj wyszukiwania liniowego.

  • Pomyłka o jeden w warunku i granicach

    Jeśli lo i hi są obie włącznie, pętla musi mieć postać while (lo <= hi). Z lo < hi ostatni pozostały element nigdy nie zostanie sprawdzony i wyszukiwanie przeoczy wartości na brzegu. Równie ważne: lo = mid + 1 i hi = mid - 1. Z lo = mid pę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 + hi może przekroczyć największą wartość int i stać się ujemne. Wtedy mid jest niepoprawnym indeksem. Bezpieczna jest wersja:

    int mid = lo + (hi - lo) / 2;

    hi - lo nigdy 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.

Powiązane artykuły