Основы программирования на С++ для начинающих

Контейнеры STL: multimap. Часть 8

Мы рассмотрели простой пример использования map<> для подсчёта вхождения отдельных литер в текст. Для этой цели мы использовали контейнер map<>. Но библиотека STL нам предоставляет и другой (близкий) тип контейнера — это multimap<>, который допускает наличие многих элементов (pair<>) в своём составе с одинаковыми значениями ключей.

Естественно, что основные правила функционирования multimap<> изменятся (по сравнению с map<>). Для такого контейнера будут следующие отличия в поведении:

  • Содержит упорядоченные пары <ключ,значение>, где ключ и значение могут принадлежать к произвольным типам;

  • Элементы с любыми значениями ключа не должны быть уникальными, в упорядоченной последовательности элементов (по ключу) такие эквивалентные элементы представлены, как разные элементы, и располагаются они друг за другом;

  • Поскольку ключи могут совпадать, то операция добавления новой пары в таблицу (метод insert()) всегда успешна. Поэтому нет смысла возвращать результат такой операции: возвращаемое значение — void;

  • Поскольку теперь в контейнере может находиться много элементов с равными ключами, то вводится дополнительный метод count(). Он получает параметром значение ключа, возвращает число вхождений элементов, имеющих такой ключ, в контейнер;

  • Операции удаления (метод erase()) с указанием ключа удаляемого элемента удаляет все сразу элементы с совпадающими ключами;

Посмотрим как multimap<> справится с предыдущей задачей. Вот текстовые файлы для тестирования программы:

30  Brother_And_Sister11  Humpty-Dumpty34  Jabberwock

Как и в предыдущем примере, используется несколько громоздкий ввод символов из потока, содержащего текст во много строк. Это связано с тем, что а). хотелось бы читать и символы пробела тоже как символы, а не как разделители и б). можно было бы просто последовательно читать символы из cin с последующим исключением переводов строки. Но в показанном варианте хотелось бы сохранить независимость от используемой операционной системы (различие так называемого DOS и UNIX перевода строки). В остальной части код стал много короче и проще.

Результат того, что мы получили, показан ниже (рядом повторено для сравнения то же действие, выполняемое map<>):

класс multimap c++, контейнеры STL, multimap для начинающих
multimap
класс map c++, контейнеры STL, map для начинающих
map

Обратим внимание на то, как единичным оператором удаления alphabet.erase( ‘a’ ) мы удалили из таблиц 38 элементов, определяющихся ключом ‘a’. Откуда взялся размер size() в 696 элементов?

класс multimap c++, контейнеры STL, multimap для начинающих

(Показанная форма команды wc вычисляет в операционной системе Linux число строк в файле. Команда ls выводит длину файла, т.е. число отдельных байт, символов в файле. В Windows вы можете попытаться добиться некоторого подобного результата используя команду dir.)

Если мы из общего числа символов (длины в байтах) вычтем число строк (переводов строк) в файле, то мы и получим эту цифру: 726 – 30 = 696. Таким образом, для каждого символа входного потока был создан отдельный элемент таблицы, например, с ключом ‘s’ было 39 таких элементов.

Всё, ранее сказанное относительно контейнера map<> (кроме алгоритма помещения и выборки) в полной мере относится и к multimap<>, например, требование сравнимости ключей и то, как определить или переопределить операцию сравнения.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *