Бинарный поиск
Бинарный поиск (двоичный поиск, метод деления пополам) — это алгоритм поиска элемента в упорядоченном массиве данных, основанный на последовательном сравнении искомого значения со средним элементом массива и сужении области поиска вдвое на каждом шаге. Относится к классу алгоритмов «разделяй и властвуй». Гарантирует нахождение элемента за логарифмическое время O(log n), что делает его одним из наиболее эффективных методов поиска в отсортированных структурах данных.
История
Первое известное описание бинарного поиска в систематизированном виде принадлежит американскому математику и инженеру Джону Мочли, который в 1946 году в лекциях по информатике предложил алгоритм для поиска в отсортированных списках. Однако практическое применение алгоритма стало возможным только с развитием электронных вычислительных машин. В 1960-х годах бинарный поиск был формализован и включён в стандартные библиотеки алгоритмов. Ключевую роль в популяризации метода сыграла книга Дональда Кнута «Искусство программирования» (том 3, 1973 год), где бинарному поиску посвящён отдельный раздел. В советской информатике алгоритм широко применялся с 1960-х годов в системах управления базами данных и научных расчётах.
Принцип работы
Алгоритм бинарного поиска применим только к предварительно отсортированным данным (по возрастанию или убыванию). Основные этапы:
- Определение границ: задаются левая (
left) и правая (right) границы интервала поиска. Для массива длинойnначальные значения:left = 0,right = n-1. - Вычисление среднего индекса:
mid = (left + right) // 2(целочисленное деление). В некоторых реализациях для избежания переполнения используют формулуmid = left + (right - left) // 2. - Сравнение: элемент
array[mid]сравнивается с искомым значениемkey:
- Если
array[mid] == key— элемент найден, возвращается его индекс. - Если
array[mid] < key— поиск продолжается в правой половине:left = mid + 1. - Если
array[mid] > key— поиск продолжается в левой половине:right = mid - 1.
- Повторение: шаги 2-3 выполняются до тех пор, пока
left <= right. Если границы смыкаются и элемент не найден, возвращается признак отсутствия (обычно-1).
Пример
Для массива [2, 5, 8, 12, 16, 23, 38, 45, 56, 69] и поиска числа 23:
| Шаг | left | right | mid | array[mid] | Сравнение |
|---|---|---|---|---|---|
| 1 | 0 | 9 | 4 | 16 | 16 < 23 → сдвиг вправо |
| 2 | 5 | 9 | 7 | 45 | 45 > 23 → сдвиг влево |
| 3 | 5 | 6 | 5 | 23 | 23 == 23 → найдено |
Классификация
Бинарный поиск имеет несколько вариантов реализации, различающихся по условиям применения и возвращаемым результатам:
По типу данных
- Дискретный бинарный поиск: применяется к статическим массивам фиксированного размера (например, в оперативной памяти).
- Бинарный поиск в отсортированном потоке: используется, когда данные поступают последовательно, но уже отсортированы (например, в файловых системах).
- Бинарный поиск по предикату: применяется для поиска границы, где некоторое условие (предикат) перестаёт выполняться. Например, поиск максимального числа
x, для которогоf(x) <= target.
По поведению при наличии дубликатов
- Поиск первого вхождения (левая граница): когда в массиве несколько одинаковых элементов, возвращается индекс первого из них.
- Поиск последнего вхождения (правая граница): возвращается индекс последнего элемента, равного ключу.
- Стандартный поиск (произвольное): возвращается любой индекс, где элемент равен ключу; при существовании дубликатов поведение не определено.
По типу данных и структуре
- Бинарный поиск в массиве: классический вариант для непрерывных массивов.
- Бинарный поиск в связном списке: редко используется из-за необходимости последовательного доступа, что сводит на нет преимущество по скорости.
- Бинарный поиск в дереве: лежит в основе сбалансированных деревьев поиска (AVL, красно-чёрных), где каждый узел хранит ключ, а левое и правое поддеревья — меньшие и большие элементы.
Реализация на языках программирования
Пример на C
``c int binarySearch(int arr[], int size, int target) { int left = 0, right = size - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == target) return mid; if (arr[mid] < target) left = mid + 1; else right = mid - 1; } return -1; } ``
Пример на Python
``python def binary_search(arr, target): left, right = 0, len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return -1 ``
Сложность
- Временная сложность: в худшем и среднем случаях O(log n), в лучшем (при попадании в середину) O(1).
- Пространственная сложность: O(1) для итеративной версии, O(log n) для рекурсивной (из-за стека вызовов).
Сравнение с другими методами поиска:
| Алгоритм | Временная сложность (худший случай) | Требование к данным |
|---|---|---|
| Линейный поиск | O(n) | Не требуют сортировки |
| Бинарный поиск | O(log n) | Обязательна сортировка |
| Интерполяционный | O(log log n) в среднем | Равномерное распределение данных |
| Поиск прыжками | O(√n) | Требуется сортировка |
Применение
В информатике и программировании
- Поиск в отсортированных массивах (например, в словарях, каталогах, базах данных с индексом).
- Реализация функций стандартной библиотеки (например,
bsearch()в C,bisectв Python,Arrays.binarySearch()в Java). - Поиск корней уравнений методом бинарного поиска (бисекции) — если функция монотонна на интервале.
- В алгоритмах сжатия данных (например, поиск кода по таблице).
- В игровых движках для ускорения поиска объектов по сетке.
В научных расчётах
- Решение уравнений с одной переменной (бисекция) — численный метод, не требующий вычисления производной.
- Оптимизация параметров модели, когда проверяемое значение монотонно зависит от параметра.
В базах данных
- Бинарный поиск лежит в основе индексации по B-деревьям (B-Tree), используемым в большинстве реляционных СУБД (например, PostgreSQL, MySQL).
- Поиск по первичному ключу в таблицах.
В повседневных алгоритмах
- Поиск в телефонных книгах, словарях, энциклопедиях (все предварительно отсортированы по алфавиту).
- Оптимизация загрузки оборудования — подбор подходящего размера буфера, времени ожидания.
- В криптографии — поиск по секретному ключу на основе «угадывания» с помощью временной боковой атаки.
Ошибки и подводные камни
Несмотря на кажущуюся простоту, бинарный поиск подвержен ряду ошибок при реализации:
- Выход за границы массива при вычислении
mid, особенно еслиleft + rightпревышает максимальное значение целого числа (в языках с фиксированной разрядностью — C, C++, Java). Используется формулаmid = left + (right - left) / 2. - Бесконечный цикл при неправильном обновлении границ (например,
left = midвместоleft = mid + 1, илиright = midвместоright = mid - 1). - Неравномерное разделение при работе с плавающими числами — необходимо учитывать погрешность.
- Отсутствие проверки на пустой массив — может вызвать деление на ноль при вычислении
mid. - Неправильная обработка дубликатов — если требуется найти именно первое или последнее вхождение, стандартный бинарный поиск может вернуть любое из них.
Интересные факты
- По данным исследований, проведённых в начале 2000-х годов, около 90% профессиональных программистов неспособны написать правильную реализацию бинарного поиска с первой попытки из-за граничных условий.
- В 2006 году в языке Java была обнаружена ошибка в реализации бинарного поиска в классе
Arrays(COLT-1456), связанная с переполнением при вычислении среднего индекса. Ошибка была исправлена только через несколько лет. - Бинарный поиск является частным случаем более общего метода — поиска делением пополам (binary search on a monotonic function), который применяется не только к массивам, но и к любым монотонным функциям.
- В российских учебниках по информатике для средней школы (например, Босова Л.Л., «Информатика») бинарный поиск традиционно изучается в 9-11 классах как один из основных алгоритмов обработки массивов.
Источники
- Кнут Д. Искусство программирования. Том 3: Сортировка и поиск. — М.: Вильямс, 2007.
- Кормен Т., Лейзерсон Ч., Ривест Р., Штайн К. Алгоритмы: построение и анализ. — М.: Вильямс, 2016.
- Бентли Д. Жемчужины программирования. — СПб.: Питер, 2007.
- Bosova L.L. Informatics: textbook for 9th grade. — Moscow: Prosveshchenie, 2020.
- Wikipedia: Binary search algorithm (accessed 2025).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →