Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:
21.7.4. Алгоритм copy_if
Алгоритм
copy
выполняет копирование без каких-либо условий. Алгоритм unique_copy
отбрасывает повторяющиеся соседние элементы, имеющие одинаковые значения. Третий алгоритм копирует только элементы, для которых заданный предикат является истинным.
template<class In,class Out,class Pred>
Out copy_if(In first,In last,Out res,Pred p)
// копирует элементы, удовлетворяющие предикату
{
while (first!=last) {
if (p(*first)) *res++ = *first;
++first;
}
return res;
}
Используя
Larger_than
из раздела 21.4, можем найти все элементы последовательности, которые больше шести.
void f(const vector<int>& v)
// копируем все элементы, которые больше шести
{
vector<int> v2(v.size);
copy_if(v.begin,v.end,v2.begin,Larger_than(6));
// ...
}
copy_if
. В таком случае просто воспользуйтесь определением, данным в этом разделе. 21.8. Сортировка и поиск
map
и set
, или выполняя сортировку. Наиболее распространенной и полезной операцией сортировки в библиотеке STL является функция sort
, которую мы уже несколько раз использовали. По умолчанию функция sort
в качестве критерия сортировки использует оператор <
, но мы можем задавать свои собственные критерии.
template<class Ran> void sort(Ran first, Ran last);
template<class Ran,class Cmp> void sort(Ran first,Ran last,Cmp cmp);
В качестве примера сортировки, основанной на критерии, определенном пользователем, покажем, как упорядочить строки без учета регистра.
struct No_case { // lowercase(x) < lowercase(y)
bool operator(const string& x, const string& y) const
{
for (int i = 0; i<x.length; ++i) {
if (i == y.length) return false; // y<x
char xx = tolower(x[i]);
char yy = tolower(y[i]);
if (xx<yy) return true; // x<y
if (yy<xx) return false; // y<x
}
if (x.length==y.length) return false; // x==y
return true; // x<y (в строке x меньше символов)
}
};
void sort_and_print(vector<string>& vc)
{
sort(vc.begin,vc.end,No_case);
for (vector<string>::const_iterator p = vc.begin;
p!=vc.end; ++p)
cout << *p << '\n';
}
find
; вместо этого можно использовать бинарный поиск, учитывающий порядок следования элементов. По существу, бинарный поиск сводится к следующему. Предположим, что мы ищем значение x; посмотрим на средний элемент.
• Если значение этого элемента равно
x
, мы нашли его! • Если значение этого элемента меньше
x
, то любой элемент со значением х
находится справа, поэтому мы просматриваем правую половину (применяя бинарный поиск к правой половине). • Если значение этого элемента больше
x
, то любой элемент со значением х
находится слева, поэтому мы просматриваем левую половину (применяя бинарный поиск к левой половине). • Если мы достигли последнего элемента (перемещаясь влево или вправо) и не нашли значение
x
, то в контейнере нет такого элемента.
find
(представляющий собой линейный поиск). Алгоритмы бинарного поиска в стандартной библиотеке называются binary_search
и equal_range
. Что мы понимаем под словом “длинные”? Это зависит от обстоятельств, но десяти элементов обычно уже достаточно, чтобы продемонстрировать преимущество алгоритма binary_search
над алгоритмом find
. На последовательности, состоящей из тысячи элементов, алгоритм binary_search
работает примерно в 200 раз быстрее, чем алгоритм find
, потому что он имеет сложность O(log2N) (см. раздел 21.6.4). Алгоритм
binary_search
имеет два варианта.
template<class Ran, class T>
bool binary_search(Ran first,Ran last,const T& val);
template<class Ran,class T,class Cmp>
bool binary_search(Ran first,Ran last,const T& val,Cmp cmp);
binary_search
просто сообщает, содержит ли контейнер заданное значение.
void f(vector<string>& vs) // vs упорядочено
{
if (binary_search(vs.begin,vs.end,"starfruit")) {
// в контейнере есть строка "starfruit"
}
// ...
}
binary_search
— идеальное средство, если нас интересует, есть заданное значение в контейнере или нет. Если нам нужно найти этот элемент, мы можем использовать функции lower_bound
, upper_bound
или equal_range
(разделы 23.4 и Б.5.4). Как правило, это необходимо, когда элементы контейнера представляют собой объекты, содержащие больше информации, чем просто ключ, когда в контейнере содержатся несколько элементов с одинаковыми ключами или когда нас интересует, какой именно элемент удовлетворяет критерию поиска.
Поделиться с друзьями: