C++. Сборник рецептов - [88]

Шрифт
Интервал

, а также демонстрирует некоторые из его уникальных операций.

Пример 6.5. Использование list

>#include

>#include

>#include

>#include


>using namespace std;


>// Простая функция для печати

>template

>struct printer {

> void operator()(const T& s) {

>  cout << s << '\n';

> }

>};


>bool inline even(int n) {

> return(n % 2 == 0);

>}


>printer strPrinter;

>printer intPrinter;


>int main() {

> list lstOne;

> list lstTwo;

> lstOne.push_back("Red");

> lstOne.push_back("Green");

> lstOne.push_back("Blue");

> lstTwo.push_front("Orange");

> lstTwo.push_front("Yellow");

> lstTwo.push_front("Fuschia");

> for_each(lstOne.begin(), // Напечатать каждый элемент списка,

>  lstOne.end(),           // используя пользовательскую функцию печати

>  strPrinter);

> lstOne.sort(); // list содержит методы для сортировки

> lstTwo.sort();

> lstOne.merge(lstTwo);    // Объединить два списка и напечатать

> for_each(lstOne.begin(), // результаты (перед объединением списки должны

>  lstOne.end(),           // быть отсортированы)

>  strPrinter);

> list intLst;

> intLst.push_back(0);

> intLst.push_back(1);

> intLst.push_back(2);

> intLst.push_back(3);

> intLst.push_back(4);

> // Удалить все значения больше 2

> intLst.remove_if(bind2nd(greater(), 2));

> for_each(intLst.begin(), intLst.end(), intPrinter);

> // Или удалить все четные значения

> intLst.remove_if(even);

>}

Обсуждение

>list — это последовательность, обеспечивающая постоянную сложность операций вставки и удаления элементов в произвольную позицию, но обладающая линейной сложностью их поиска. Обычно >list реализуется как двухсвязный список, что означает, что каждый элемент хранится в узле, содержащем указатели на предыдущий и следующий элементы последовательности. Он обеспечивает все требования к контейнеру стандартной последовательности, полюс предоставляет несколько уникальных методов.

Объявление >list не вызывает сложностей — просто укажите тип элементов, которые в нем будут храниться, и, опционально, класс распределителя памяти.

>list

> typename Allocator = allocator > // Используемый распределитель

>                                         // памяти

Параметр шаблона >Value — это тип элементов, которые будут храниться в >list. Это должен быть тип, который поддерживает конструктор копирования и присвоение. >Allocator — это используемый класс распределителя памяти. По умолчанию используется стандартный распределитель (и в большинстве случаев его вполне достаточно).

Далее приведено типичное объявление >list (см. пример 6.5).

>list lstOne;

После объявления списка поместите в него что-нибудь с помощью >push_front или >push_back, как здесь.

>lstOne.push_back("Red"); // Добавление элементов в конец списка

>lstOne.push_back("Green");

>lstOne.push_back("Blue");


>lstTwo.push_front("Orange"); // Добавление элементов в начало

>lstTwo.push_front("Yellow");

>lstTwo.push_front("Fuschia");

Помещение элементов в >list занимает постоянное время, а не амортизированное постоянное время, как в случае с >vector. Реализации >list не требуется периодически изменять размер буфера, так что в них не будет возникать периодических падений производительности, как при использовании >vector. >list просто должен обновить набор указателей, и больше ничего.

Для удаления элементов из начала или конца >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 strlst;

>list::iterator p;

>// ...

>string s = "Scion";

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

> "Toyota");

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

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

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


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


Фундаментальные алгоритмы и структуры данных в Delphi

Книга "Фундаментальные алгоритмы и структуры данных в Delphi" представляет собой уникальное учебное и справочное пособие по наиболее распространенным алгоритмам манипулирования данными, которые зарекомендовали себя как надежные и проверенные многими поколениями программистов. По данным журнала "Delphi Informant" за 2002 год, эта книга была признана сообществом разработчиков прикладных приложений на Delphi как «самая лучшая книга по практическому применению всех версий Delphi».В книге подробно рассматриваются базовые понятия алгоритмов и основополагающие структуры данных, алгоритмы сортировки, поиска, хеширования, синтаксического разбора, сжатия данных, а также многие другие темы, тесно связанные с прикладным программированием.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.


Как пасти котов. Наставление для программистов, руководящих другими программистами

«Как пасти котов» – это книга о лидерстве и руководстве, о том, как первое совмещать со вторым. Это, если хотите, словарь трудных случаев управления IT-проектами. Программист подобен кошке, которая гуляет сама по себе. Так уж исторически сложилось. Именно поэтому так непросто быть руководителем команды разработчиков. Даже если вы еще месяц назад были блестящим и дисциплинированным программистом и вдруг оказались в роли менеджера, вряд ли вы знаете, с чего надо начать, какой выбрать стиль руководства, как нанимать и увольнять сотрудников, проводить совещания, добиваться своевременного выполнения задач.