- •Стандартные алгоритмы
- •Обрабатываемые последовательности
- •Нечто, что может быть вызвано как функция
- •Алгоритмы сортировки
- •Сортировка (sort)
- •Устойчивая сортировка (stable_sort)
- •Частичная сортировка (partial_sort)
- •Частичная сортировка с копированием (partial_sort_copy)
- •N-й элемент (nth_element)
- •Алгоритмы поиска
- •Нижняя граница (lower_bound)
- •Верхняя граница (upper_bound)
- •Область вставки (equal_range)
- •Двоичный поиск (binary_search)
Алгоритмы поиска
Алгоритмы двоичного поиска вместо итераторов произвольного доступа (RandomAccessIterator) используют итераторы последовательного доступа (ForwardIterator). При использовании таких итераторов число выполняемых сравнений приблизительно равно длине последовательности. В случае использования итераторов произвольного доступа количество сравнений будет равно логарифму от длины последовательности. Для сравнения элементов между собой как и в алгоритмах сортировки используется либоoperator< либо явно заданны критерий сравненияcompare
Обратите внимание – данные алгоритмы работают только с уже отсортированной последовательностью! Если исходная последовательность не отсортирована, то использование алгоритмов поиска даст случайный результат.
Нижняя граница (lower_bound)
template <class ForwardIterator, class T>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
const T& value);
template <class ForwardIterator, class T, class Compare>
ForwardIterator lower_bound(ForwardIterator first,
ForwardIterator last, const T& value, Compare comp);
Алгоритм lower_boundнаходит первую позицию, в которую элемент со значениемvalueможет быть вставлен без нарушения упорядоченности последовательности.lower_boundвозвращает самый «ближний к началу последовательности» итераторiв диапазоне[first, last)такой, что для любого итератораj в диапазоне[first, i)выполняются следующие соответствующие условия:*j < valueилиcomp(*j, value) == true. Проще говоря, значения всех элементов, стоящих в последовательности до позицииi, меньше чемvalue, а значения последующих элементов больше или равны value.Делается максимумlog(last - first) + 1сравнений. Также не стоит забывать о том, что этот алгоритм (как иupper_bound) возвращает итератор на элемент, где должно было бы находиться значениеvalue, при этом в позиции, указываемой итератором, может находиться элемент со значением, не равным заданному.
Верхняя граница (upper_bound)
template <class ForwardIterator, class T>
ForwardIterator upper_bound(ForwardIterator first,
ForwardIterator last, const T& value);
template <class ForwardIterator, class T, class Compare>
ForwardIterator upper_bound(ForwardIterator first,
ForwardIterator last, const T& value, Compare comp);
Алгоритм upper_boundнаходит последнюю позицию, в которуюvalueможет быть вставлено без нарушения упорядочения.upper_boundвозвращает самый «дальний от начала последовательсности» итераторiв диапазоне[first, last)такой, что для любого итератораjв диапазоне[first, i)выполняются следующие соответствующие условия:!(value < *j)илиcomp(value, *j) == false. Отличие от предыдущего алгоритма состоит в том, что все элементы, значение которых также равноvalue (если таковые вообще имеются), теперь размещаются перед, а не после данного элемента. Делается максимумlog(last - first) + 1сравнений.
Область вставки (equal_range)
template <class ForwardIterator, class T>
pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first,
ForwardIterator last, const T& value);
template <class ForwardIterator, class T, class Compare>
pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first,
ForwardIterator last, const T& value, Compare comp);
Алгоритм equal_range находит самый большой поддиапазон [i, j) такой, что значение может быть вставлено по любому итератору k в нём. k удовлетворяет соответствующим условиям: !(*k < value) && !(value < *k) или comp(*k, value) == false && comp(value, *k) == false. Данный алгоритм возвращает пару итераторов, первый из которых эквивалентен результату действияlower_bound, а второй -upper_bound. Эти итераторы ограничивают последовательность элементов со значениями, равнымиvalue.Таким образом, после работы алгоритма весьма просто провести проверку, существует ли в последовательности элемент со значением, равным искомому. Нужно сопоставить полученные итераторы – если они равны, то была возвращена пустая подпоследовательность и, следовательно, элемента с заданным значением в исходной последовательности нет. При работе алгоритма делается максимум2*log(last - first) + 1 сравнений.
Пример использования, equal_range, lower_bound и upper_bound.
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
// Вспомогательный массив
int ary[] = {4, 5, 1, 3, 2, 3, 2, 5, 1, 2, 4, 3, 4, 1, 5 };
vector<int> v1(ary,ary+sizeof(ary)/sizeof(ary[0]));
vector<int>::iterator i;
// Выведем исходное содержимое вектора на экран
for (i=v1.begin(); i!=v1.end(); ++i)
cout << *i << " ";
cout << endl;
// Отсортируем v1
sort (v1.begin(),v1.end());
// И снова выведем содержимое v1 на экран
for (i=v1.begin(); i!=v1.end(); ++i) cout << *i << " ";
cout << endl;
// Найдем нижнюю и верхнюю границы для 3
vector<int>::iterator lower_bnd = lower_bound(v1.begin(),v1.end(),3);
vector<int>::iterator upper_bnd = upper_bound(v1.begin(),v1.end(),3);
pair <vector<int>::iterator,vector<int>::iterator> range;
range = equal_range (v1.begin(),v1.end(),3);
// выведем полученные результаты
cout << "*lower_bnd == " << *lower_bnd <<endl;
cout << "*upper_bnd ==" << *upper_bnd <<endl;
cout << "*range.first and *range.second == " << *range.first << ":"
<< *range.second << ")" <<endl;
cout << "distance(v1.begin(),lower_bnd) == "
<< distance(v1.begin(),lower_bnd) <<endl;
cout << "distance(v1.begin(),upper_bnd) == "
<< distance(v1.begin(),upper_bnd) <<endl;
cout << "distance(v1.begin(),range.first) == "
<< distance(v1.begin(),range.first) <<endl;
cout << "distance(v1.begin(),range.second) == "
<< distance(v1.begin(),range.second) <<endl;
return 0;
}
Вывод программы:
4 5 1 3 2 3 2 5 1 2 4 3 4 1 5
1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
*lower_bnd == 3
*upper_bnd ==4
*range.first and *range.second == 3:4)
distance(v1.begin(),lower_bnd) == 6
distance(v1.begin(),upper_bnd) == 9
distance(v1.begin(),range.first) == 6
distance(v1.begin(),range.second) == 9