Программирование. Принципы и практика использования C++ Исправленное издание, стр. 294
enjoyable: 1facilities: 2flexible: 1for: 3general: 1is: 2language: 1language.: 1make: 1minor: 1more: 1new: 1of: 1programmer.: 1programming: 3provided: 1provides: 1purpose: 1serious: 1superset: 1the: 3to: 2types.: 1Если не хотите проводить различие между верхним и нижним регистрами букв или учитывать знаки пунктуации, то можно решить и эту задачу: см. упр. 13.
21.6.2. Обзор ассоциативных массивов
Так что же такое контейнер map? Существует много способов реализации ассоциативных массивов, но в библиотеке STL они реализованы на основе сбалансированных бинарных деревьев; точнее говоря, они представляют собой красно-черные деревья. Мы не будем вдаваться в детали, но поскольку вам известны эти технические термины, вы можете найти их объяснение в литературе или в веб.
Дерево состоит из узлов (так же как список состоит из узлов; см. раздел 20.4). В объекте класса
Node
Вот как может выглядеть объект класса
map<Fruit,int>
Поскольку ключ хранится в члене класса
Nodefirstleft–>first<first && first<right–>firstИначе говоря, для каждого узла выполняются два условия.
• Ключ его левого подузла меньше ключа узла.
• Ключ узла меньше, чем ключ правого подузла.
В узле могут храниться дополнительные данные, которые контейнер может использовать для поддержки баланса. Дерево считается сбалансированным, если каждый узел имеет примерно одинаковое количество наследников как слева, так и справа. Если дерево, состоящее из N узлов, сбалансировано, то для обнаружения узла необходимо просмотреть не больше log2N узлов. Это намного лучше, чем N/2 узлов в среднем, которые мы должны были бы просмотреть, если бы ключи хранились в списке, а поиск выполнялся с начала (в худшем случае линейного поиска нам пришлось бы просмотреть N узлов). (См. также раздел 21.6.4.)
Для примера покажем, как выглядит несбалансированное дерево.

Это дерево по-прежнему удовлетворяет критерию, требующему, чтобы ключ каждого узла был больше ключа левого подузла и меньше ключа правого.
left–>first<first && first<right–>firstИ все же это дерево является несбалансированным, поэтому нам придется совершить три перехода, чтобы найти узлы Apple и Kiwi, вместо двух, как в сбалансированном дереве. Для деревьев, содержащих много узлов, эта разница может оказаться существенной, поэтому для реализации контейнеров
mapРазбираться в принципах организации деревьев, используемых для реализации контейнера
mapmaptemplate<class Key, class Value, class Cmp = less<Key> > class map{ // ... typedef pair<Key,Value> value_type; // контейнер map хранит // пары (Key,Value) typedef sometype1 iterator; // указатель на узел дерева typedef sometype2 const_iterator; iterator begin(); // указывает на первый элемент iterator end(); // указывает на следующий за последним // элемент Value& operator[](const Key& k); // индексирование // по переменной k iterator find(const Key& k); // поиск по ключу k void erase(iterator p); // удаление элемента, на который // указывает итератор p pair<iterator, bool> insert(const value_type&); // вставляет пару (key,value) // ...};Настоящий вариант контейнера определен в заголовке
<map>Node*