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

Материал из Викиконспекты
Перейти к: навигация, поиск
(Принцип работы)
Строка 1: Строка 1:
 
{{Определение
 
{{Определение
 
|definition=
 
|definition=
'''Целочисленный двоичный поиск (бин. поиск)''' - алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку.  
+
'''Целочисленный двоичный поиск (бин. поиск)''' {{---}} алгоритм поиска объекта по заданному признаку во множестве объектов, упорядоченных по тому же самому признаку.  
 
}}
 
}}
  
 
== Формулировка задачи ==
 
== Формулировка задачи ==
Пусть нам дан упорядоченный массив, состоящий только из целочисленых элементов. Нам надо найти в нем индекс, по которому находится искомый элемент, или же мы можем находить интервалы вхождения искомого элемента. Для этой задачи мы и можем использовать двоичный поиск.
+
Пусть нам дан упорядоченный массив, состоящий только из целочисленных элементов. Нам надо найти в нем индекс, по которому находится искомый элемент, или же мы можем находить интервалы вхождения искомого элемента. Для этой задачи мы и можем использовать двоичный поиск.
  
 
==Принцип работы==
 
==Принцип работы==
Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остается та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие - это левосторонний/правосторонний двоичный поиск.
+
Двоичный поиск заключается в том, что на каждом шаге множество объектов делится на две части и в работе остается та часть множества, где находится искомый объект. Или же, в зависимости от постановки задачи, мы можем остановить процесс, когда мы получим первый или же последний индекс вхождения элемента. Последнее условие {{---}} это левосторонний/правосторонний двоичный поиск.
  
 
== Правосторонний/левосторонний целочисленный двоичный поиск ==
 
== Правосторонний/левосторонний целочисленный двоичный поиск ==
Когда мы ищем правосторонним бин. поиском, то он возвращает индекс самого правого вхождения заданного значения <b>х</b>.<br>
+
Когда мы ищем правосторонним бин. поиском, то он возвращает индекс самого правого вхождения заданного значения <tex> x </tex> .
Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения <b>х</b>.<br>
+
 
Это разделение помогает находить количество подряд идущих равных значений.<br>
+
Когда же поиск левосторонний, возвращается индекс самого левого вхождения заданного значения <tex> x </tex> .
 +
 
 +
Это разделение помогает находить количество подряд идущих равных значений.
 +
 
 
<b><i>Например:</i></b> <br>
 
<b><i>Например:</i></b> <br>
Задан отсортированный массив [1, 2, 2, 2, 2, 3, 5, 8, 9, 11] <br>
+
Задан отсортированный массив <tex>[1, 2, 2, 2, 2, 3, 5, 8, 9, 11]</tex>
Правосторонний поиск двойки выдаст в результате 5, в то время как левосторонний выдаст 2. <br>
+
 
От сюда следует, что количество подряд идущих двоек равно длине отрезка [2;5] = 4. <br>
+
Правосторонний поиск двойки выдаст в результате <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] <= k</tex>).
+
В случае правостороннего поиска изменится знак сравнения при сужении границ на (<tex>a[m] \leqslant k</tex>).
  
Инвариант цикла: пусть левый индекс меньше или равен искомого элемента, а правый строго больше, тогда если <tex>l = r - 1</tex>, то понятно, что <tex>l</tex> самое правое вхождение (так как следующее уже больше).
+
Инвариант цикла: пусть левый индекс меньше или равен искомого элемента, а правый {{---}} строго больше, тогда если <tex>l = r - 1</tex>, то понятно, что <tex>l</tex> {{---}} самое правое вхождение (так как следующее уже больше).
  
 
== Источники ==
 
== Источники ==

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

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


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

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

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

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

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

Когда мы ищем правосторонним бин. поиском, то он возвращает индекс самого правого вхождения заданного значения [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-е издание)

Ссылки

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