Программирование >>  Разработка устойчивых систем 

1 ... 94 95 96 [ 97 ] 98 99 100 ... 196


CharGen g:

generate(v. v + SZ. g):

generate(v2. v2 + SZ. g):

sort(v. V + SZ);

sort(v2. v2 + SZ):

print(v, V + SZ. v . ):

pr1nt(v2. v2 + SZ. v2 . ):

bool b = includes(v. v + SZ, v + SZ/2, v + SZ):

cout.setf(ios::boolalpha):

cout includes: b endl:

char v3[SZ*2 + 1], *end:

end = set union(v, v + SZ. v2. v2 + SZ. v3):

print(v3. end. set union , ):

end = setJntersGCtion(v. v + SZ.

v2. v2 + SZ. v3): print(v3, end. set intersection . ): end = set difference(v. v + SZ. v2. v2 + SZ. v3): pnnt(v3. end, set difference . ): end = set symmetric difference(v. v + SZ.

v2. v2 + SZ. v3): print(v3. end. set symmetric difference . ); } III:-

После заполнения, сортировки и вывода векторов v и v2 алгоритм includes() проверяет, содержится ли вторая половина вектора v во всем интервале v. Естественно, это условие заведомо выполняется, поэтому проверка всегда дает положительный результат. Просмотрите результаты вызова алгоритмов set umon(), setJntersection(), set difference() и set symmetric difference() и убедитесь в том, что они работают так, как положено.

Операции с кучей

Кучей называется структура данных, напоминающая массив и используемая при реализации приоритетной очереди - интервала с возможностью выборки элементов по приоритету, определяемому некоторой функцией сравнения. В стандартную библиотеку включен набор операций, позволяющих интерпретировать интервал как кучу , которая всегда обеспечивает эффективную выборку элемента с наибольшим приоритетом без полного упорядочения всего интервала.

Как и в случае с операциями сортировки, каждый алгоритм существует в двух версиях. Первая версия предполагает, что при сравнении используется внутренний оператор <. Вторая форма проверяет условие а<Ь при помощи операторной функции operatorO(а,Ь) объекта StrictWeakOrdering.

void make heap(RandomAccessIterator first.

RandomAccessIterator last): void make heap(RandomAccessIterator first.

RandomAccessIterator last, StrictWeakOrdering binary pred):

Алгоритм преобразует произвольный интервал в кучу.

void push heap(RandomAccessIterator first.

RandomAccessIterator last): void push hGap(RandomAccessIterator first.

RandomAccessIterator last. StrictWeakOrdering binary pred):

Алгоритм включает элемент *(last-l) в кучу, определяемую интервалом [firstlast-1). Иначе говоря, последний элемент помещается в правильную позицию кучи.



void pop heap(RandomAccessIterator first.

RandomAccessIterator last): void pop heap(RandomAccessIterator first.

RandomAccessIterator last, StrictWeakOrdering binary pred):

Алгоритм помещает наибольщий элемент (который перед выполнением этой операции находится в позиции *first по самому определению кучи) в позицию (last-1) и переупорядочивает остальные элементы так, чтобы они сохраняли правильный порядок следования. Если ограничиться простой выборкой с позиции *first, то следующий элемент не будет следующим по величине элементом кучи. По этой причине необходимо использовать алгоритм pop heap(), чтобы в куче сохранялся правильный порядок следования элементов приоритетной очереди.

void sort heap(RandomAccessIterator first.

RandomAccessIterator last): void sort heap(RandomAccessIterator first,

RandomAccessIterator last. StrictWeakOrdering binary pred):

Алгоритм может рассматриваться как обратный по отношению к mal<e heap(): он берет интервал, элементы которого размещены в порядке кучи, и переупорядочивает его в обычном порядке сортировки, так что интервал перестает быть кучей. Это означает, что после вызова sort heap() для интервала уже нельзя вызывать функции push heap() и pop heap() (вернее, можно, но ничего разумного они уже не сделают). Итоговая сортировка не является устойчивой, то есть относительный порядок следования элементов не сохраняется.

Применение операции к каждому элементу интервала

Алгоритмы следующей группы перебирают все элементы интервала и выполняют с каждым элементом некоторую операцию. Они различаются по принципу использования результата этой операции: алгоритм for each() игнорирует возвращаемые значения, а transform () помещает их в приемный интервал (который может совпадать с исходным интервалом).

UnaryFunction for each(InputIterator first. Inputlterator last. UnaryFunction f):

Алгоритм применяет объект функции f к каждому элементу интервала [firstlast). Возвращаемое значение каждого отдельного применения f игнорируется. Если f является обычным указателем на функцию, возвращаемое значение обычно интереса не представляет; но если f является объектом с внутренним состоянием, он может накапливать результаты применения f к элементам интервала. Окончательным возвращаемым значением алгоритма for each() является f.

Outputlterator transform(Inputlterator first,

Inputlterator last. Outputlterator result. UnaryFunction f): Outputlterator transform(Inputlteratorl first,

Inputlteratorl last, InputIterator2 f1rst2.

Outputlterator result, BinaryFunction f):

Алгоритм transform(), как и for each(), применяет объект функции f к каждому элементу интервала [firstlast). Но вместо того чтобы игнорировать результаты вызовов функции, transform() копирует их (оператором =) в *result и инкремен-тирует result после каждого копирования. Интервал, на который ссылается ите-



ратор result, должен содержать достаточное количество элементов. Если вы не уверены в этом, используйте итератор вставки и создавайте новые элементы вместо присваивания.

Первая форма transforni() просто вызывает f(*first), где first последовательно перебирает элементы исходного интервала. Вторая форма вызывает f(*firstl,*first2) (длина второго интервала определяется длиной первого интервала). Возвращаемое значение в обоих случаях представляет собой конечный итератор полученного интервала.

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

Начнем с алгоритма for each(). Он перебирает содержимое интервала, последовательно берет каждый элемент и передает его объекту функции, переданному при вызове. В принципе for each() делает то, что вы могли бы запрограммировать вручную; определение for each() в заголовочном файле компилятора выглядит примерно так:

template <class Inputlterator. class Funct1on>

Function for each(Inputlterator first. Inputlterator last, Function f) { while (first != last)

f(*first++): return f:

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

: СОб:Counted.h

Класс, отслеживающий свои объекты #ifndef COUNTED H #define COUNTED H #i nclude <vector> #include <iostream>

class Counted {

static int count:

char* ident: public:

Counted(char* id) : ident(id) { count++: } -CountedO { std::cout ident count = --count std::endl:

class CountedVector : public std::vector<Counted*> { public: CountedVector(char* id) { for(int i = 0: i < 5: i++) push back(new Counted(id)):

#endif COUNTED H /:-

: C06:Counter.cpp {0} #include Counted.h



1 ... 94 95 96 [ 97 ] 98 99 100 ... 196

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