Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

Для удаления элементов из начала или конца

list
используйте
pop_front
или
pop_back
(без аргументов). Несмотря на их имя, методы «pop» не возвращают извлекаемый элемент, как это можно ожидать, исходя из обычной семантики стеков.

Обычно

list
выглядит так, как показано на рис. 6.2. Каждый узел содержит (по меньшей мере) три части: объект, в нем содержащийся, указатель на предыдущий узел и указатель на следующий узел. В оставшейся части рецепта я буду ссылаться на указатели на следующий и предыдущий узлы как
next_
и
prev_
.

Рис. 6.2.

Список с двунаправленными связями

Когда вы увидите, как реализован

list
, станет очевидно, почему некоторые операции имеют сложность, отличную от их сложности для
vector
. Добавление элемента в любое место
list
требует только изменения указателей
next_
и
prev_
предыдущего и следующего элементов. Приятным моментом в
list
является то, что при вставке и удалении элементов в помощью
insert
и
erase
устаревают значения только тех итераторов, которые указывают на затрагиваемый(е) объект(ы). Итераторы для других элементов не теряют актуальности.

Методы вставки и удаления — это

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

list<string> strlst;

list<string>::iterator p;

// ...

string s = "Scion";

p = find(strLst.begin, strLst.end, // std::find из <algorithm>

 "Toyota");

strLst.insert(p, s); // Вставить s сразу перед p

strLst.insert(p, 16, s); // Вставить 16 копий s непосредственно перед p

strLst insert(p, myOtherStrLst.begin, // Вставить все, что содержится

 myOtherStrLst.end); // в myOtherStrLst, перед p

Удаление элементов аналогично.

p = find(strLst.begin, strLst.end, // std::find из <algorithm>

 "Toyota");

strLst1.erase(p); // Удаляем этот элемент

strLst2.erase(p, strLst.end); // Удаляем от p до конца

strLst3.clear; // Удаляем все элементы

В дополнение к методам стандартных контейнеров

list
предоставляет несколько своих. Первый — это
splice
.

splice
делает то, что означает его имя: он объединяет два
list
в один. Вот как можно объединить
lstTwo
с
lstOne
из примера 6.5.

list<string>::iterator p = // Находим, куда вставить второй

 std::find(lstOne.begin, // список

lstOne.end, "Green");

lstOne.splice(p, lstTwo); // Вставляем lstTwo непосредственно перед "Green"

p
— это итератор, который указывает на элемент в
lstOne
.
lstTwo
вставляется в
lstTwo
непосредственно перед
p
. Как и в случае со вставкой, все, что здесь требуется сделать, — это изменить указатели
next_
и
prev_
соответствующих узлов, так что эта операция занимает постоянное время. После объединения
lstTwo
с
lstOne
первый очищается, и именно поэтому этот параметр не объявлен как
const
. Также можно вставить в
lstOne
один элемент или диапазон элементов из
lstTwo
. В обоих случаях элементы, объединяемые с другим списком, удаляются из первоначального.

Если списки отсортированы (

list
содержит свой собственный метод
sort
,
std::sort
с
list
не работает) и требуется объединить их в один, сохранив их порядок, то вместо
splice
используйте
merge
.
merge
объединяет два списка в один, и если два элемента оказываются одинаковыми, то в конечную версию попадает элемент из
lstOne
. Как и в случае со
splice
, список, переданный в качестве аргумента, по окончании объединения очищается.

Также

list
содержит несколько удобных операций для удаления элементов. Представьте, что вам требуется удалить все вхождения какого-либо элемента. Все, что для этого требуется сделать, это вызвать
remove
, передав такой аргумент, который при сравнении с элементами
list
будет давать
(*p == item) != false
, где
p
— это итератор
list
.
remove
вызывается вот так.

strLst.remove("Harry");

В результате из

strLst
будут удалены все элементы, у которых
el == "Harry"
. Если требуется удалить элементы, которые удовлетворяют какому-либо предикату, такому как больше какого-либо значения, используйте
remove_if
.

bool inline even(int n) {

 return(n % 2 == 0);

}

list<int> intLst;

// Fill up intLst...

intLst.remove_if(even); // Удаляет все элементы, для которых even(*p)

// != false

Если предикаты более сложные, то попробуйте использовать какие-то из функторов из

<functional>
. Например, если требуется удалить элементы, которые больше определенного значения, используйте в
remove_if
объединение из
greater
(из
<algorithm>
) и
bind2nd
.

intLst.remove_if(std::bind2nd(std::greater<int>, 2));

В результате этого из

intLst
будут удалены все значения, которые больше 2. Эта запись несколько необычна, но ничего сложного в ней нет.
bind2nd
принимает два аргумента — объект функции (назовем ее
f
) и значение (
v
) — и возвращает объект функции, который принимает один аргумент (
arg
) и вызывает
f(arg, v)
.
bind2nd
— это простой способ делать подобные вещи без необходимости писать набор небольших функций.

Поделиться:
Популярные книги

Вамп

Парсиев Дмитрий
3. История одного эволюционера
Фантастика:
рпг
городское фэнтези
постапокалипсис
5.00
рейтинг книги
Вамп

Император

Рави Ивар
7. Прометей
Фантастика:
фэнтези
7.11
рейтинг книги
Император

Книга 4. Игра Кота

Прокофьев Роман Юрьевич
4. ОДИН ИЗ СЕМИ
Фантастика:
фэнтези
боевая фантастика
рпг
6.68
рейтинг книги
Книга 4. Игра Кота

Род Корневых будет жить!

Кун Антон
1. Тайны рода
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Род Корневых будет жить!

Царев врач, или Когда скальпель сильнее клинка

Сапаров Александр Юрьевич
1. Царев врач
Фантастика:
попаданцы
альтернативная история
8.77
рейтинг книги
Царев врач, или Когда скальпель сильнее клинка

Под маской моего мужа

Рам Янка
Любовные романы:
современные любовные романы
5.67
рейтинг книги
Под маской моего мужа

Пять попыток вспомнить правду

Муратова Ульяна
2. Проклятые луной
Фантастика:
фэнтези
эпическая фантастика
5.00
рейтинг книги
Пять попыток вспомнить правду

Курсант: Назад в СССР 7

Дамиров Рафаэль
7. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 7

Пышка и Герцог

Ордина Ирина
Фантастика:
юмористическое фэнтези
историческое фэнтези
фэнтези
5.00
рейтинг книги
Пышка и Герцог

Все ведьмы – стервы, или Ректору больше (не) наливать

Цвик Катерина Александровна
1. Все ведьмы - стервы
Фантастика:
юмористическая фантастика
5.00
рейтинг книги
Все ведьмы – стервы, или Ректору больше (не) наливать

Кодекс Охотника. Книга XXI

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

Возвышение Меркурия. Книга 14

Кронос Александр
14. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 14

Идеальный мир для Лекаря 2

Сапфир Олег
2. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 2

Котенок. Книга 3

Федин Андрей Анатольевич
3. Котенок
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Котенок. Книга 3