У цьому підручнику пояснюється двійковий пошук і рекурсивний двійковий пошук в Java, а також його алгоритм, реалізація та приклади коду двійкового пошуку в Java:
Бінарний пошук в Java - це техніка, яка використовується для пошуку цільового значення або ключа в колекції. Це техніка, яка використовує метод "розділяй і володарюй" для пошуку ключа.
Колекцію, до якої буде застосовано бінарний пошук для пошуку ключа, потрібно відсортувати за зростанням.
Зазвичай більшість мов програмування підтримують методи лінійного пошуку, бінарного пошуку та хешування, які використовуються для пошуку даних у колекції. Ми розглянемо хешування в наших наступних уроках.
Бінарний пошук у Java
Лінійний пошук є базовою технікою, яка полягає в послідовному обході масиву і порівнянні кожного елемента з ключем до тих пір, поки не буде знайдено ключ або не буде досягнуто кінця масиву.
Лінійний пошук рідко використовується на практиці. Бінарний пошук є найбільш часто використовуваною технікою, оскільки він набагато швидший за лінійний пошук.
Java надає три способи виконання бінарного пошуку:
- Використання ітеративного підходу
- Використання рекурсивного підходу
- Використання методу Arrays.binarySearch ().
У цьому підручнику ми застосуємо та обговоримо всі ці 3 методи.
Алгоритм бінарного пошуку в Java
У методі бінарного пошуку колекція багаторазово ділиться навпіл і ключовий елемент шукається в лівій або правій половині колекції, залежно від того, чи є ключ меншим або більшим за середній елемент колекції.
Простий алгоритм бінарного пошуку виглядає наступним чином:
- Розрахуйте середній елемент колекції.
- Порівняйте ключові елементи із середнім елементом.
- Якщо ключ = середній елемент, ми повертаємо середню позицію індексу для знайденого ключа.
- Else Якщо ключ - середній елемент, то ключ лежить у правій половині колекції. Таким чином, повторити кроки з 1 по 3 для нижньої (правої) половини колекції.
- Якщо ключ <середній елемент, то ключ знаходиться у верхній половині колекції. Отже, потрібно повторити бінарний пошук у верхній половині.
Як ви можете бачити з наведених вище кроків, у бінарному пошуку половина елементів колекції ігнорується вже після першого порівняння.
Зауважте, що та сама послідовність кроків справедлива як для ітеративного, так і для рекурсивного двійкового пошуку.
Проілюструємо алгоритм бінарного пошуку на прикладі.
Наприклад, візьмемо наступний відсортований масив з 10 елементів.
Обчислимо середину масиву.
Mid = 0+9/2 = 4
#1) Key = 21
Спочатку ми порівняємо значення ключа з елементом [mid] і знайдемо, що значення елемента mid = 21.
Таким чином, ми бачимо, що key = [mid], а отже ключ знаходиться у позиції 4 у масиві.
#2) Key = 25
Спочатку ми порівнюємо значення ключа з серединою. Оскільки (21 <25), ми будемо шукати ключ безпосередньо у верхній половині масиву.
Тепер знову знайдемо середину для верхньої половини масиву.
Середина = 4+9/2 = 6
Значення в позиції [mid] = 25
Тепер ми порівнюємо ключовий елемент із середнім елементом, тобто (25 == 25), отже, ми знайшли ключ у позиції [mid] = 6.
Таким чином, ми багаторазово ділимо масив і, порівнюючи ключовий елемент з серединою, вирішуємо, в якій половині шукати ключ. Бінарний пошук більш ефективний з точки зору часу і коректності, а також набагато швидший.
Реалізація бінарного пошуку на Java
Використовуючи наведений вище алгоритм, реалізуємо програму бінарного пошуку на Java з використанням ітераційного підходу. У цій програмі ми беремо приклад масиву і виконуємо бінарний пошук у цьому масиві.
import java.util.*; class Main{ public static void main(String args[]){ int numArray[] = {5,10,15,20,25,30,35}; System.out.println("Вхідний масив: " + Arrays.toString(numArray)); //ключ для пошуку int key = 20; System.out.println("\nКлюч для пошуку=" + key); //встановити перший індекс int first = 0; //встановити передостанній індекс int last = numArray.length-1; //обчислити серединуarray int mid = (first + last)/2; //доки first та last не перетинаються while( first <= last ){ //якщо mid <ключ, то шуканий ключ знаходиться в першій половині масиву if ( numArray[mid] last ){ System.out.println("Елемент не знайдено!"); } } }
Виходьте:
Вхідний масив: [5, 10, 15, 20, 25, 30, 35].
Ключ для пошуку=20
Елемент знайдено за індексом: 3
Наведена вище програма демонструє ітераційний підхід до бінарного пошуку. Спочатку оголошується масив, потім визначається ключ для пошуку.
Після обчислення середини масиву, ключ порівнюється з середнім елементом. Потім, в залежності від того, чи є ключ меншим або більшим за ключ, виконується пошук ключа в нижній або верхній половині масиву відповідно.
Рекурсивний бінарний пошук у Java
Ви також можете виконати двійковий пошук за допомогою техніки рекурсії. Тут метод двійкового пошуку викликається рекурсивно, поки не буде знайдено ключ або не буде вичерпано весь список.
Нижче наведено програму, яка реалізує рекурсивний бінарний пошук:
import java.util.*; class Main{ //рекурсивний метод бінарного пошуку public static int binary_Search(int intArray[], int low, int high, int key){ //якщо масив впорядкований, то виконати бінарний пошук по масиву if (high>=low){ //обчислити середину int mid = low + (high - low)/2; //якщо key =intArray[mid] повернути mid if (intArray[mid] == key){ повернути mid; } //якщо intArray[mid] == key, то ключ знаходиться зліваполовину масиву if (intArray[mid]> key){ return binary_Search(intArray, low, mid-1, key);//рекурсивний пошук ключа }else //ключ знаходиться в правій половині масиву { return binary_Search(intArray, mid+1, high, key);//рекурсивний пошук ключа } } return -1; } public static void main(String args[]){ //обчислюємо масив та ключ intArray[] = {1,11,21,31,41,51,61,71,81,91}; System.out.println("InputСписок: " + Arrays.toString(intArray)); int key = 31; System.out.println("\nКлюч для пошуку:" + key); int high=intArray.length-1; //викликаємо бінарний метод пошуку int result = binary_Search(intArray,0,high,key); //виводимо результат if (result == -1) System.out.println("\nКлюч не знайдено у заданому списку!"); else System.out.println("\nКлюч знайдено за адресою: "+результат + " у списку"); } }
Виходьте:
Список вхідних даних: [1, 11, 21, 31, 41, 51, 61, 71, 81, 91
Ключ, який треба шукати:
Ключ знаходиться за адресою: 3 у списку
Використання методу Arrays.binarySearch ().
Клас Arrays в Java надає метод binarySearch (), який виконує двійковий пошук у заданому масиві. Цей метод приймає масив і ключ для пошуку в якості аргументів і повертає позицію ключа в масиві. Якщо ключ не знайдено, то метод повертає -1.
У наведеному нижче прикладі реалізовано метод Arrays.binarySearch ().
import java.util.Arrays; class Main{ public static void main(String args[]){ //означити масив int intArray[] = {10,20,30,40,50,60,70,80,90}; System.out.println("Вхідний масив Array : " + Arrays.toString(intArray)); //означити ключ для пошуку int key = 50; System.out.println("\nКлюч, за яким буде здійснюватись пошук: " + key); //викликати метод binarySearch для заданого масиву з ключем, за яким здійснюється пошук int result =Arrays.binarySearch(intArray,key); //вивести результат if (result <0) System.out.println("\nКлюч не знайдено в масиві!"); else System.out.println("\nКлюч знайдено за адресою index: "+результат + " в масиві."); } }
Виходьте:
Вхідні дані Array : [10, 20, 30, 40, 50, 60, 70, 80, 90].
Ключ для пошуку:50
Ключ знаходиться в масиві за індексом: 4.
Поширені запитання
Питання #1) Як написати бінарний пошук?
Відповідай: Бінарний пошук зазвичай виконується шляхом ділення масиву на дві половини. Якщо ключ, який потрібно знайти, більший за середній елемент, то шукається верхня половина масиву шляхом подальшого ділення і пошуку в підмасиві, доки ключ не буде знайдений.
Аналогічно, якщо ключ менший за середній елемент, то ключ шукається у нижній половині масиву.
Q #2) Де використовується бінарний пошук?
Відповідай: Двійковий пошук в основному використовується для пошуку відсортованих даних у програмних додатках, особливо коли обсяг пам'яті компактний і обмежений.
Q #3) У чому полягає велике "О" бінарного пошуку?
Відповідай: Часова складність бінарного пошуку дорівнює O (logn), де n - кількість елементів у масиві. Просторова складність бінарного пошуку дорівнює O (1).
Q #4) Чи є бінарний пошук рекурсивним?
Відповідай: Так, оскільки бінарний пошук є прикладом стратегії "розділяй і володарюй" і може бути реалізований за допомогою рекурсії. Ми можемо розділити масив навпіл і викликати один і той самий метод для виконання бінарного пошуку знову і знову.
Q #5) Чому це називається бінарним пошуком?
Відповідай: Алгоритм бінарного пошуку використовує стратегію "розділяй і володарюй", яка багаторазово розрізає масив навпіл або на дві частини. Тому він і називається бінарним пошуком.
Висновок
Бінарний пошук є часто використовуваною технікою пошуку в Java. Вимога до виконання бінарного пошуку полягає в тому, що дані повинні бути відсортовані в порядку зростання.
Бінарний пошук можна реалізувати за допомогою ітеративного або рекурсивного підходу. Клас Arrays в Java також надає метод 'binarySearch', який виконує бінарний пошук в масиві.
У наступних уроках ми розглянемо різні методи сортування в Java.