Целочисленный двоичный поиск — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Отмена правки 37175 участника 194.85.161.2 (обсуждение))
Строка 1: Строка 1:
 
{{Определение
 
{{Определение
 
|definition=
 
|definition=
'''Целочисленный двоичный поиск (бин. поиск)''' {{---}} алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку.  
+
'''Целочисленный двоичный поиск (бин. поиск) <i>(от англ. Binary Search)</i>''' {{---}} алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку.  
 
}}
 
}}
  
 
== Формулировка задачи ==
 
== Формулировка задачи ==
Пусть нам дан упорядоченный массив, состоящий только из целочисленных элементов. Нам надо найти в нем индекс, по которому находится искомый элемент, или же мы можем находить интервалы вхождения искомого элемента. Для этой задачи мы и можем использовать двоичный поиск.
+
Пусть нам дан упорядоченный массив, состоящий только из целочисленных элементов. Нам надо найти в нём индекс, по которому находится искомый элемент, или же мы можем находить интервалы вхождения искомого элемента. Для этой задачи мы и можем использовать двоичный поиск.
  
 
==Принцип работы==
 
==Принцип работы==
Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остается та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие {{---}} это левосторонний/правосторонний двоичный поиск.
+
Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остаётся та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие {{---}} это левосторонний/правосторонний двоичный поиск.
  
 
== Правосторонний/левосторонний целочисленный двоичный поиск ==
 
== Правосторонний/левосторонний целочисленный двоичный поиск ==
Когда мы ищем правосторонним бин. поиском, то он возвращает индекс самого правого вхождения заданного значения <tex> x </tex> .
+
Когда мы ищем правосторонним бинарным поиском, то он возвращает индекс самого правого вхождения заданного значения <tex> x </tex> .
  
 
Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения <tex> x </tex> .
 
Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения <tex> x </tex> .
Строка 33: Строка 33:
  
 
== Код ==
 
== Код ==
<pre>binSearch(l, r)               // l, r - левая и правая границы
+
<pre>binSearch(l, r)               // l, r - левая и правая границы
  while l < r - 1             // запускаем цикл
+
    while l < r - 1                 // запускаем цикл
    m = (l + r) / 2;         // m - середина области поиска
+
        m = (l + r) / 2;           // m - середина области поиска
    if a[m] < k
+
        if a[m] < k
      l = m;  
+
            l = m;  
    else  
+
        else  
      r = m;                  // сужение границ
+
            r = m;                  // сужение границ
 
</pre>
 
</pre>
 
В случае правостороннего поиска изменится знак сравнения при сужении границ на (<tex>a[m] \leqslant k</tex>).
 
В случае правостороннего поиска изменится знак сравнения при сужении границ на (<tex>a[m] \leqslant k</tex>).
Строка 51: Строка 51:
 
==Ссылки==
 
==Ссылки==
 
[http://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA Википедия - двоичный поиск]
 
[http://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA Википедия - двоичный поиск]
 +
 +
 +
[[Категория: Дискретная математика и алгоритмы]]
 +
[[Категория: Сортировки]]

Версия 22:01, 22 мая 2014

Определение:
Целочисленный двоичный поиск (бин. поиск) (от англ. Binary Search) — алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку.


Формулировка задачи

Пусть нам дан упорядоченный массив, состоящий только из целочисленных элементов. Нам надо найти в нём индекс, по которому находится искомый элемент, или же мы можем находить интервалы вхождения искомого элемента. Для этой задачи мы и можем использовать двоичный поиск.

Принцип работы

Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остаётся та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие — это левосторонний/правосторонний двоичный поиск.

Правосторонний/левосторонний целочисленный двоичный поиск

Когда мы ищем правосторонним бинарным поиском, то он возвращает индекс самого правого вхождения заданного значения [math] x [/math] .

Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения [math] x [/math] .

Это разделение помогает находить количество подряд идущих равных значений.

Например:
Задан отсортированный массив [math][1, 2, 2, 2, 2, 3, 5, 8, 9, 11][/math]

Правосторонний поиск двойки выдаст в результате [math]5[/math], в то время как левосторонний выдаст [math]2[/math].

От сюда следует, что количество подряд идущих двоек равно длине отрезка [math][2;5][/math], то есть [math]4[/math].

Если искомого элемента в массиве нет, то правосторонний поиск выдаст минимальный элемент, больший искомого, а левосторонний наоборот, максимальный элемент, меньший искомого.

Алгоритм двоичного поиска

Схема бин. поиска

Идея поиска заключается в том, чтобы брать элемент посередине, между границами, и сравнивать его с искомым. В случае равенства возвращать его, а если искомое больше(в случае правостороннего — не меньше), чем элемент сравнения, то сужаем область поиска так, чтобы новая левая граница была равна индексу середины предыдущей области. В противном случае присваиваем это значение правой границе. Проделываем эту процедуру до тех пор, пока правая граница больше левой более чем на [math]1[/math], или же пока мы не найдём искомый индекс.

Код

binSearch(l, r)                // l, r - левая и правая границы
    while l < r - 1                 // запускаем цикл
        m = (l + r) / 2;            // m - середина области поиска
        if a[m] < k
            l = m; 
        else 
            r = m;                  // сужение границ

В случае правостороннего поиска изменится знак сравнения при сужении границ на ([math]a[m] \leqslant k[/math]).

Инвариант цикла: пусть левый индекс меньше или равен искомого элемента, а правый — строго больше, тогда если [math]l = r - 1[/math], то понятно, что [math]l[/math] — самое правое вхождение (так как следующее уже больше).

Источники

  • Д. Кнут - Искусство программирования (Том 3, 2-е издание)

Ссылки

Википедия - двоичный поиск