Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих.pdf
Скачиваний:
183
Добавлен:
01.05.2014
Размер:
3.97 Mб
Скачать

lexicographical_compare() выполняет лексикографическое (словарное) упорядочение

equal(), includes(), lexicographical_compare(), max(), max_element(),

(см. также обсуждение перестановок и Приложение). min(), min_element(), mismatch()

12.5.8. Алгоритмы работы с множествами

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

set_union(), set_intersection(), set_difference(),

контейнеров, но не обоим. set_symmetric_difference()

12.5.9. Алгоритмы работы с хипом

Хип (heap) – это разновидность двоичного дерева, представленного в массиве. Стандартная библиотека предоставляет такую реализацию хипа, в которой значение ключа в любом узле больше либо равно значению ключа в любом потомке этого узла.

make_heap(), pop_heap(), push_heap(), sort_heap()

12.6.Когда нельзя использовать обобщенные алгоритмы

Ассоциативные контейнеры (отображения и множества) поддерживают определенный порядок элементов для быстрого поиска и извлечения. Поэтому к ним не разрешается применять обобщенные алгоритмы, меняющие порядок, такие, как sort() и partition(). Если в ассоциативном контейнере требуется переставить элементы, то необходимо сначала скопировать их в последовательный контейнер, например в вектор или список.

Контейнер list (список) реализован в виде двусвязного списка: в каждом элементе, помимо собственно данных, хранятся два члена-указателя – на следующий и на предыдущий элементы. Основное преимущество списка – это эффективная вставка и удаление одного элемента или целого диапазона в произвольное место списка, а недостаток – невозможность произвольного доступа. Например, можно написать:

vector<string>::iterator vec_iter = vec.begin() + 7;

Такая форма вполне допустима и инициализирует vec_iter адресом восьмого элемента

//ошибка: арифметические операции над итераторами

//не поддерживаются списком

вектора, но запись

list<string>::iterator list_iter = slist.begin() + 7;

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

Поскольку список не поддерживает произвольного доступа, то алгоритмы merge(), remove(), reverse(), sort() и unique() лучше к таким контейнерам не применять, хотя ни один из них явно не требует наличия соответствующего итератора. Вместо этого для списка определены специализированные версии названных операций в виде функций-членов, а также операция splice():

list::merge() объединяет два отсортированных списка

list::remove() удаляет элементы с заданным значением

list::remove_if()удаляет элементы, удовлетворяющие некоторому условию

list::reverse() переставляет элементы списка в обратном порядке

list::sort() сортирует элементы списка

list::splice() перемещает элементы из одного списка в другой

list::unique() оставляет один элемент из каждой цепочки одинаковых смежных элементов

12.6.1. Операция list_merge()

void list::merge( list rhs );

template <class Compare>

void list::merge( list rhs, Compare comp );

Элементы двух упорядоченных списков объединяются либо на основе оператора “меньше”, определенного для типа элементов в контейнере, либо на основе указанной пользователем операции сравнения. (Заметьте, что элементы списка rhs перемещаются в список, для которого вызвана функция-член merge(); по завершении операции список rhs будет пуст.) Например:

int array1[ 10 ] = { 34, 0, 8, 3, 1, 13, 2, 5, 21, 1 }; int array2[ 5 ] = { 377, 89, 233, 55, 144 };

list< int > ilist1( array1, array1 + 10 ); list< int > ilist2( array2, array2 + 5 );

// для объединения требуется, чтобы оба списка были упорядочены

ilist1.sort(); ilist2.sort(); ilist1.merge( ilist2 );

После выполнения операции merge() список ilist2 пуст, а ilist1 содержит первые 15 чисел Фибоначчи в порядке возрастания.

12.6.2. Операция list::remove()

void list::remove( const elemType &value );

Операция remove() удаляет все элементы с заданным значением:

ilist1.remove( 1 );

12.6.3. Операция list::remove_if()

template < class Predicate

>

void list::remove_if( Predicate pred );

Операция remove_if() удаляет все элементы, для которых выполняется указанное

class Even { public:

bool operator()( int elem ) { return ! (elem % 2 ); }

};

условие, т.е. предикат pred возвращает true. Например: ilist1.remove_if( Even() );

удаляет все четные числа из списка, определенного при рассмотрении merge().

12.6.4. Операция list::reverse()

void list::reverse();

Операция reverse() изменяет порядок следования элементов списка на противоположный:

ilist1.reverse();

12.6.5. Операция list::sort()

void list::sort(); template <class

Compare>

void list::sort( Compare comp );

По умолчанию sort() упорядочивает элементы списка по возрастанию с помощью оператора “меньше”, определенного в классе элементов контейнера. Вместо этого можно явно передать в качестве аргумента оператор сравнения. Так,

list1.sort();

упорядочивает list1 по возрастанию, а

list1.sort( greater<int>() );

упорядочивает list1 по убыванию, используя оператор “больше”.

12.6.6. Операция list::splice()

void list::splice( iterator pos, list rhs );

void list::splice( iterator pos, list rhs, iterator ix );

void list::splice( iterator pos, list rhs, iterator first, iterator last );

Операция splice() имеет три формы: перемещение одного элемента, всех элементов или диапазона из одного списка в другой. В каждом случае передается итератор, указывающий на позицию вставки, а перемещаемые элементы располагаются

int array[ 10 ] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 };

list< int > ilist1( array, array + 10 );

непосредственно перед ней. Если даны два списка:

list< int > ilist2( array, array + 2 ); // содержит 0, 1

то следующее обращение к splice() перемещает первый элемент ilist1 в ilist2. Теперь ilist2 содержит элементы 0, 1 и 0, тогда как в ilist1 элемента 0 больше нет.