Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Липпман.doc
Скачиваний:
8
Добавлен:
14.08.2019
Размер:
7.54 Mб
Скачать

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() удаляет все элементы, для которых выполняется указанное условие, т.е. предикат pred возвращает true. Например:

class Even {

public:

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

};


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 больше нет.

// ilist2.end() указывает на позицию, куда нужно переместить элемент

// элементы вставляются перед этой позицией

// ilist1 указывает на список, из которого перемещается элемент

// ilist1.begin() указывает на сам перемещаемый элемент


ilis2.splice( ilist2.end(), ilist1, ilist1.begin() );

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

list< int >::iterator first, last;

first = ilist1.find( 2 );

last = ilist1.find( 13 );


ilist2.splice( ilist2.begin(), ilist1, first, last );

В данном случае элементы 2, 3, 5 и 8 удаляются из ilist1 и вставляются в начало ilist2. Теперь ilist1 содержит пять элементов 1, 1, 13, 21 и 34. Для их перемещения в ilist2 можно воспользоваться третьей вариацией операции splice():

list< int >::iterator pos = ilist2.find( 5 );


ilist2.splice( pos, ilist1 );

Итак, список ilist1 пуст. Последние пять элементов перемещены в позицию списка ilist2, предшествующую той, которую занимает элемент 5.

12.6.7. Операция list::unique()

void list::unique();

template <class BinaryPredicate>


void list::unique( BinaryPredicate pred );

Операция unique() удаляет соседние дубликаты. По умолчанию при сравнении используется оператор равенства, определенный для типа элементов контейнера. Например, если даны значения {0,2,4,6,4,2,0}, то после применения unique() список останется таким же, поскольку в соседних позициях дубликатов нет. Но если мы сначала отсортируем список, что даст {0,0,2,2,4,4,6}, а потом применим unique(), то получим четыре различных значения {0,2,4,6}.

ilist.unique();

Вторая форма unique() принимает альтернативный оператор сравнения. Например,

class EvenPair {

public:

bool operator()( int val1, val2 )

{ return ! (val2 % val1 ); }

};


ilist.unique( EvenPair() );

удаляет соседние элементы, если второй элемент без остатка делится на первый.

Эти операции, являющиеся членами класса, следует предпочесть соответствующим обобщенным алгоритмам при работе со списками. Остальные обобщенные алгоритмы, такие, как find(), transform(), for_each() и т.д., работают со списками так же эффективно, как и с другими контейнерами (еще раз напомним, что подробно все алгоритмы рассматриваются в Приложении).

Упражнение 12.8

Измените программу из раздела 12.2, используя список вместо вектора.