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

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

(который для своих аргументов вызывает >operator<), а можно передать в него собственный предикат сортировки. Пример 6.10 показывает, как сохранить строки в >set.

Пример 6.10. Хранение строк в set

>#include

>#include

>#include


>using namespace std;


>int main() {

> set setStr;

> string s = "Bill";

> setStr.insert(s);

> s = "Steve";

> setStr.insert(s);

> s = "Randy";

> setStr.insert(s);

> s = "Howard";

> setStr.insert(s);

> for (set::const_iterator p = setStr.begin();

>  p != setStr.end(); ++p)

>  cout << *p << endl;

>}

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

>Bill

>Howard

>Randy

>Steve

Обсуждение

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

Поддерживаются вставка и поиск элементов, но, как и список, набор не позволяет производить произвольный доступ к элементам. Если требуется получить что-то из набора, то можно найти элемент с помощью метода >find или перебрать элементы с помощью >set::iterator или >set::const_iterator. Объявление набора имеет знакомый вид.

>set

> typename LessThanFun = std::less, // Функция/Функтор

>                                        // используемый для сортировки

> typename Alloc = std::allocator > // Распределитель памяти

Указывать >Key требуется всегда, иногда требуется предоставить собственную >LessThanFun, а указывать собственный распределитель требуется очень редко (так что я не буду здесь его описывать).

Параметр шаблона >Key — это, как и в случае с другими стандартными контейнерами, тип сохраняемых элементов. Для >set он определяется через >typedef как >set::key_type, так что доступ к нему есть при выполнении программы. Класс >Key должен обеспечивать конструктор копирования и присвоение, и все.

Пример 6.10 показывает, как использовать >set для строк. Использование набора для хранения объектов других типов работает точно так же — объявите набор с именем класса в качестве параметра шаблона.

>std::set setMyObjs;

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

Пример 6.11. Хранение указателей в set

>#include

>#include

>#include

>#include

>#include


>using namespace std;


>// Класс для сравнения строк, переданных через указатели

>struct strPtrLess {

> bool operator()(const string* p1,

>  const string* p2) {

>  assert(p1 && p2);

>  return(*p1 < *p2);

> }


> int main() (

>  set setStrPtr; // Передаем специальный

>                                      // «меньше чем» функтор

> string s1 = "Tom";

> string s2 = "Dick";

> string s3 = "Harry";

> setStrPtr.insert(&s1);

> setStrPtr.insert(&s2);

> setStrPtr.insert(&s3);

> for (set::const_iterator p =

>  setStrPtr.begin(); p != setStrPtr.end(); ++p)

>  cout << **p << endl; // Разыменовываем итератор и то, на что

>                       // он указывает

>}

>strPtrLess возвращает истину, если строка, на которую указывает >p1, меньше, чем та, на которую указывает >p2. Это делает его двоичным предикатом, так как он принимает два аргумента и возвращает >bool. Так как >operator< определен для >string, для сравнения я использую именно его. На самом деле, если требуется использовать более общий подход, используйте для предиката сравнения шаблон класса

>template

>class ptrLess {

>public:

> bool operator()(const T* p1,

>  const T* p2) {

>  assert(p1 && p2);

>  return(*p1 < *p2);

> }

>};

Это работает для указателей на любые объекты, для которых определен >operator<. Объявление набора с его использованием имеет такой вид.

>set > setStrPtr;

>set поддерживает многие из функций, поддерживаемых другими стандартными последовательными контейнерами (например, >begin, >end, >size, >max_size) и другими ассоциативными контейнерами (например, >insert, >erase, >clear, >find).

При использовании >set помните, что при каждом изменении состояния набора выполняется его сортировка. Когда число его элементов велико, логарифмическая сложность добавления или удаления элементов может оказаться очень большой — вам действительно требуется, чтобы объекты сортировались каждый раз? Если нет, то для повышения производительности используйте >vector или >list и сортируйте его только тогда, когда это необходимо, что обычно имеет сложность порядка n*log(n).


Рекомендуем почитать
Изучаем 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, новые средства многопоточности и др.


Создаем порт для FreeBSD своими руками. Часть II

Система сборки программ, используемая во FreeBSD, имеет значительно большие возможности, чем те, которые мы задействовали. Какие это возможности и как их использовать в своих портах?


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

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


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

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