В этом учебном пособии рассказывается о двоичном поиске и рекурсивном двоичном поиске на Java, а также о его алгоритме, реализации и примерах кода двоичного поиска на Java:
Бинарный поиск в Java - это техника, которая используется для поиска целевого значения или ключа в коллекции. Это техника, которая использует метод "разделяй и властвуй" для поиска ключа.
Коллекция, к которой будет применен бинарный поиск для поиска ключа, должна быть отсортирована в порядке возрастания.
Обычно большинство языков программирования поддерживают методы линейного поиска, бинарного поиска и хэширования, которые используются для поиска данных в коллекции. Мы изучим хэширование в наших последующих уроках.
Двоичный поиск в Java
Линейный поиск - это базовый метод, при котором массив обходится последовательно, и каждый элемент сравнивается с ключом до тех пор, пока ключ не будет найден или пока не будет достигнут конец массива.
Линейный поиск редко используется в практических приложениях. Бинарный поиск является наиболее часто используемой техникой, поскольку он намного быстрее линейного поиска.
Java предоставляет три способа выполнения двоичного поиска:
- Использование итерационного подхода
- Использование рекурсивного подхода
- Использование метода Arrays.binarySearch ().
В этом учебнике мы реализуем и обсудим все эти 3 метода.
Алгоритм двоичного поиска на Java
В методе бинарного поиска коллекция многократно делится пополам, и ключевой элемент ищется в левой или правой половине коллекции в зависимости от того, меньше или больше ключ, чем средний элемент коллекции.
Простой алгоритм двоичного поиска выглядит следующим образом:
- Вычислите средний элемент коллекции.
- Сравните ключевые элементы со средним элементом.
- Если ключ = средний элемент, то мы возвращаем позицию среднего индекса для найденного ключа.
- Else Если key> mid элемент, то ключ лежит в правой половине коллекции. Таким образом, повторите шаги с 1 по 3 для нижней (правой) половины коллекции.
- Else key <mid элемент, то ключ находится в верхней половине коллекции. Следовательно, необходимо повторить бинарный поиск в верхней половине.
Как видно из приведенных выше шагов, при бинарном поиске половина элементов коллекции игнорируется сразу после первого сравнения.
Обратите внимание, что такая же последовательность шагов применима как для итеративного, так и для рекурсивного двоичного поиска.
Проиллюстрируем алгоритм двоичного поиска на примере.
Например, возьмем следующий отсортированный массив из 10 элементов.
Вычислим среднее положение массива.
Середина = 0+9/2 = 4
#1) Ключ = 21
Сначала мы сравним значение ключа с элементом [mid] и обнаружим, что значение элемента в середине = 21.
Таким образом, мы находим, что key = [mid]. Следовательно, ключ находится в позиции 4 в массиве.
#2) Ключ = 25
Сначала мы сравниваем значение ключа с mid. Поскольку (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; //вычисляем середину массива 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 int intArray[], int low, int high, int key){ //если массив в порядке, то выполняем двоичный поиск по массиву if (high>=low){ //вычисляем середину int mid = low + (high - low)/2; //если key =intArray[mid] return mid if (intArray[mid] == key){ return mid; } //если intArray[mid]> key то 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,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Ключ найден в месте: "+result + " в списке"); } }
Выход:
Входной список: [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[]){ //определяем массив intArray[] = {10,20,30,40,50,60,70,80,90}; System.out.println("Входной массив : " + Arrays.toString(intArray)); //определяем ключ для поиска int key = 50; System.out.println("\n Ключ для поиска:" + key); //вызываем метод binarySearch на данном массиве с ключом для поиска int result =Arrays.binarySearch(intArray,key); //печатаем результат возврата if (result <0) System.out.println("\nKey не найден в массиве!"); else System.out.println("\nKey найден по индексу: "+result + " в массиве."); } }
Выход:
Входной массив : [10, 20, 30, 40, 50, 60, 70, 80, 90].
Ключ для поиска:50
Ключ находится по индексу: 4 в массиве.
Часто задаваемые вопросы
Q #1) Как написать двоичный поиск?
Ответ: Бинарный поиск обычно выполняется путем деления массива на половины. Если искомый ключ больше среднего элемента, то поиск ведется в верхней половине массива путем дальнейшего деления и поиска в подмассиве до тех пор, пока ключ не будет найден.
Аналогично, если ключ меньше среднего элемента, то поиск ключа производится в нижней половине массива.
Q #2) Где используется двоичный поиск?
Ответ: Двоичный поиск в основном используется для поиска отсортированных данных в программных приложениях, особенно когда пространство памяти компактно и ограничено.
Q #3) В чем заключается большая O двоичного поиска?
Ответ: Временная сложность двоичного поиска составляет O (logn), где n - количество элементов в массиве. Пространственная сложность двоичного поиска составляет O (1).
Вопрос # 4) Является ли двоичный поиск рекурсивным?
Ответ: Да. Поскольку двоичный поиск является примером стратегии "разделяй и властвуй" и может быть реализован с помощью рекурсии, мы можем разделить массив на половины и вызывать один и тот же метод для выполнения двоичного поиска снова и снова.
Q #5) Почему он называется двоичным поиском?
Ответ: Алгоритм бинарного поиска использует стратегию "разделяй и властвуй", которая многократно разрезает массив на половинки или две части. Поэтому он называется бинарным поиском.
Заключение
Бинарный поиск является часто используемым методом поиска в Java. Требованием для выполнения бинарного поиска является то, что данные должны быть отсортированы в порядке возрастания.
Бинарный поиск может быть реализован с использованием итеративного или рекурсивного подхода. Класс Arrays в Java также предоставляет метод 'binarySearch', который выполняет бинарный поиск в массиве.
В последующих уроках мы рассмотрим различные техники сортировки в Java.