Программирование >>  Немодифицирующие последовательные алгоритмы 

1 ... 9 10 11 [ 12 ] 13 14 15 ... 78


положительным. Тогда приведенный выше вызов функции advance имеет то же действие, что и применение оператора + + к г и раз. Операции advance и distance будут выполняться гораздо быстрее для итераторов произвольного доступа, чем для итераторов других типов.

1.10. Алгоритмы replace и reverse

Алгоритм replace, упомянутый в таблице раздела 1.9, позволяет нам найти все элементы с определенным значением в заданном контейнере и заменить их другим значением. Следующая программа служит иллюстрацией сказанного:

replace.срр: Замена элементов последовательности. #include <iostream> #include <string> #include <algorithm> using namespace std;

int main()

{ char str[] = abcabcabc ; int n = strlen(str); replace(str, str+n, b, q); cout str << endl; return 0;

Программа заменяет все элементы массива str, равные b, на q, так что вывод этой программы будет следующим:

aqcaqcaqc

Алгоритм reverse, также упомянутый в таблице из раздела 1.9, позволяет легко заменить последовательность на обратную ей. Согласно этой таблице он требует двунаправленных итераторов, которые, как мы знаем, предоставляют все четыре контейнера. Давайте продемонстрируем этот алгоритм снова с использованием массива.

reverse.срр: Замена строки на обратную ей. #include <iostream> #include <string> #include <algorithm> using namespace std;

int main()

{ char str[] = abcklmxyz ;

reverse(str, str+strlen(str));

cout str endl; Будет выведено: zyxmlkcba return 0;



1.11. Возвращаясь к алгоритму sort

Функция qsort из стандартной библиотеки С является достаточно общей, потому что она принимает в качестве четвертого аргумента функцию сравнения, определяемую пользователем. При использовании алгоритма sort в разделе 1.4 подобный аргумент отсутствовал, так как sort полагался на оператор сравнения меньше чем <. Если имеем дело с массивами экземпляров класса, мы можем придать этому оператору любое значение по нашему усмотрению, но это невозможно, если элементами массива являются значения какого-либо встроенного типа, например int. Допустим, мы захотим отсортировать массив в нисходящем, а не в восходящем порядке. Конечно, это можно сделать, отсортировав массив сначала в восходящем порядке, а затем применив алгоритм reverse, обсуждавшийся в предыдущем разделе. Но мы можем решить задачу другим способом, используя алгоритм sort с третьим аргументом, который задает функцию сравнения, как в случае с qsort. Например:

dsortl.cpp: Сортировка в нисходящем порядке

с использованием функции сравнения.

#include <iostream>

#include <algorithm>

using namespace std;

bool comparefun(int x, int y)

{ return x > y;

int mainO { const int N = 8; int a[N] =

{1234, 5432, 8943, 3346, 9831, 7842, 8863, 9820}; cout << Before sorting:\n ;

copy(a, a+N, ostream iterator<int>(cout, ));

cout << endl;

sort(a, a+N, comparefun);

cout << After sorting in descending order:\n ; copy(a, a+N, ostream iterator<int>(cout, )); cout << endl; return 0;

Вспомним, что мы обсуждали использование сору для вывода, как это делается в данной программе, в конце раздела 1.9. Нам необходимо определить функцию comparefun таким образом, чтобы значение comparefun(a[i], a[j]) равнялось true тогда и только тогда, когда после сортировки a[i] должно



предшествовать аЦ]. Функции, которые подобно comparefun возвращают значение типа bool, называются предикатами. Программа создает следующий вывод:

Before sorting:

1234 5432 8943 3346 9831 7842 8863 9820

After sorting in descending order:

9831 9820 8943 8863 7842 5432 3346 1234

1.12. Введение в функциональные объекты

Существует другой способ решения задачи сортировки из предыдущего раздела. Хотя для такой простой задачи он и не нужен, обсуждаемые принципы являются важными для других более сложных случаев, поэтому не стоит пропускать этот раздел при чтении. Функциональным объектом называется класс, где определен оператор вызова, который записывается как operatorQ. От класса не требуется наличия каких-либо других членов. Давайте начнем с очень простого примера. (Здесь и далее мы пишем iostream.h вместо iostream, поскольку в последнем случае VC5 также требует наличия строчки using namespace std, а ВС5, напротив, не позволяет использовать эту строчку, если не включаются типичные заголовки STL, такие как vector.)

funobj.cpp: Очень простой функциональный объект. #include <iostream.h>

class compare { public:

int operator!)(int x, int y)const

{ return X > y;

int mainO { compare v;

cout v(2, 15) endl; Вывод: 0

cout compare 0 (5, 3) << endl; Вывод: 1

cout << endl;

return 0;

Так как для класса compare определен оператор вызова функции, operatorQ, с двумя параметрами типа int, мы можем использовать выражение v(2,15), где V - переменная этого класса. Это выражение на самом деле является сокращенной формой записи вместо v.operatorQ(2, 15) и таким образом приводит к вызову функции-члена operatorQ класса compare, возвращающей значение О, поскольку 2 не больше 15. Второй вызов

compare 0(5, 3)



1 ... 9 10 11 [ 12 ] 13 14 15 ... 78

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика