Целочисленный двоичный поиск — различия между версиями
(→Принцип работы) |
Alex700 (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
{{Определение | {{Определение | ||
|definition= | |definition= | ||
− | '''Целочисленный двоичный поиск (бин. поиск)''' - алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку. | + | '''Целочисленный двоичный поиск (бин. поиск)''' {{---}} алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку. |
}} | }} | ||
== Формулировка задачи == | == Формулировка задачи == | ||
− | Пусть нам дан упорядоченный массив, состоящий только из | + | Пусть нам дан упорядоченный массив, состоящий только из целочисленных элементов. Нам надо найти в нем индекс, по которому находится искомый элемент, или же мы можем находить интервалы вхождения искомого элемента. Для этой задачи мы и можем использовать двоичный поиск. |
==Принцип работы== | ==Принцип работы== | ||
− | Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остается та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие - это левосторонний/правосторонний двоичный поиск. | + | Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остается та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие {{---}} это левосторонний/правосторонний двоичный поиск. |
== Правосторонний/левосторонний целочисленный двоичный поиск == | == Правосторонний/левосторонний целочисленный двоичный поиск == | ||
− | Когда мы ищем правосторонним бин. поиском, то он возвращает индекс самого правого вхождения заданного значения < | + | Когда мы ищем правосторонним бин. поиском, то он возвращает индекс самого правого вхождения заданного значения <tex> x </tex> . |
− | Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения < | + | |
− | Это разделение помогает находить количество подряд идущих равных значений. | + | Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения <tex> x </tex> . |
+ | |||
+ | Это разделение помогает находить количество подряд идущих равных значений. | ||
+ | |||
<b><i>Например:</i></b> <br> | <b><i>Например:</i></b> <br> | ||
− | Задан отсортированный массив [1, 2, 2, 2, 2, 3, 5, 8, 9, 11] < | + | Задан отсортированный массив <tex>[1, 2, 2, 2, 2, 3, 5, 8, 9, 11]</tex> |
− | Правосторонний поиск двойки выдаст в результате 5, в то время как левосторонний выдаст 2 | + | |
− | От сюда следует, что количество подряд идущих двоек равно длине отрезка [2;5] | + | Правосторонний поиск двойки выдаст в результате <tex>5</tex>, в то время как левосторонний выдаст <tex>2</tex>. |
− | Если искомого элемента | + | |
+ | От сюда следует, что количество подряд идущих двоек равно длине отрезка <tex>[2;5]</tex>, то есть <tex>4</tex>. | ||
+ | |||
+ | Если искомого элемента в массиве нет, то правосторонний поиск выдаст минимальный элемент, больший искомого, а левосторонний наоборот, максимальный элемент, меньший искомого. | ||
== Алгоритм двоичного поиска == | == Алгоритм двоичного поиска == | ||
[[Файл:shcemebinsearch.png|350px|thumb|right|Схема бин. поиска]] | [[Файл:shcemebinsearch.png|350px|thumb|right|Схема бин. поиска]] | ||
Идея поиска заключается в том, чтобы брать элемент посередине, между границами, и сравнивать его с искомым. | Идея поиска заключается в том, чтобы брать элемент посередине, между границами, и сравнивать его с искомым. | ||
− | В случае равенства возвращать его, а если искомое больше(в случае правостороннего - не меньше), чем элемент сравнения, | + | В случае равенства возвращать его, а если искомое больше(в случае правостороннего {{---}} не меньше), чем элемент сравнения, |
− | то сужаем область поиска так, чтобы новая левая граница была равна индексу середины предыдущей области. В противном случае присваиваем это значение правой границе. Проделываем эту процедуру до тех пор, пока правая граница больше левой более чем на 1, или же пока мы не найдём искомый индекс. | + | то сужаем область поиска так, чтобы новая левая граница была равна индексу середины предыдущей области. В противном случае присваиваем это значение правой границе. Проделываем эту процедуру до тех пор, пока правая граница больше левой более чем на <tex>1</tex>, или же пока мы не найдём искомый индекс. |
== Код == | == Код == | ||
Строка 35: | Строка 41: | ||
r = m; // сужение границ | r = m; // сужение границ | ||
</pre> | </pre> | ||
− | В случае правостороннего поиска изменится знак сравнения при сужении границ на (<tex>a[m] | + | В случае правостороннего поиска изменится знак сравнения при сужении границ на (<tex>a[m] \leqslant k</tex>). |
− | Инвариант цикла: пусть левый индекс меньше или равен искомого элемента, а правый | + | Инвариант цикла: пусть левый индекс меньше или равен искомого элемента, а правый {{---}} строго больше, тогда если <tex>l = r - 1</tex>, то понятно, что <tex>l</tex> {{---}} самое правое вхождение (так как следующее уже больше). |
== Источники == | == Источники == |
Версия 14:01, 17 мая 2014
Определение: |
Целочисленный двоичный поиск (бин. поиск) — алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку. |
Содержание
Формулировка задачи
Пусть нам дан упорядоченный массив, состоящий только из целочисленных элементов. Нам надо найти в нем индекс, по которому находится искомый элемент, или же мы можем находить интервалы вхождения искомого элемента. Для этой задачи мы и можем использовать двоичный поиск.
Принцип работы
Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остается та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие — это левосторонний/правосторонний двоичный поиск.
Правосторонний/левосторонний целочисленный двоичный поиск
Когда мы ищем правосторонним бин. поиском, то он возвращает индекс самого правого вхождения заданного значения
.Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения
.Это разделение помогает находить количество подряд идущих равных значений.
Например:
Задан отсортированный массив
Правосторонний поиск двойки выдаст в результате
, в то время как левосторонний выдаст .От сюда следует, что количество подряд идущих двоек равно длине отрезка
, то есть .Если искомого элемента в массиве нет, то правосторонний поиск выдаст минимальный элемент, больший искомого, а левосторонний наоборот, максимальный элемент, меньший искомого.
Алгоритм двоичного поиска
Идея поиска заключается в том, чтобы брать элемент посередине, между границами, и сравнивать его с искомым. В случае равенства возвращать его, а если искомое больше(в случае правостороннего — не меньше), чем элемент сравнения, то сужаем область поиска так, чтобы новая левая граница была равна индексу середины предыдущей области. В противном случае присваиваем это значение правой границе. Проделываем эту процедуру до тех пор, пока правая граница больше левой более чем на
, или же пока мы не найдём искомый индекс.Код
binSearch(l, r) // l, r - левая и правая границы while l < r - 1 // запускаем цикл m = (l + r) / 2; // m - середина области поиска if a[m] < k l = m; else r = m; // сужение границ
В случае правостороннего поиска изменится знак сравнения при сужении границ на (
).Инвариант цикла: пусть левый индекс меньше или равен искомого элемента, а правый — строго больше, тогда если
, то понятно, что — самое правое вхождение (так как следующее уже больше).Источники
- Д. Кнут - Искусство программирования (Том 3, 2-е издание)