Иллюстрированный самоучитель по Visual Studio.Net

         

Контейнеры типа hash_multimap


Хешированный ассоциативный контейнер типа hash_multimap основан на встроенной реализации хэш-таблиц. Вы помните, что преимуществом такого типа контейнеров является быстродействие, которое в среднем значительно выше, чем у сортированных ассоциативных контейнеров. Упорядоченность элементов в таком контейнере не гарантируется, но вы можете по определенной системе добывать их С ПОМОЩЬЮ метода hash_multimap: :equal_range.

Предположим, что ваша база данных содержит сведения о сотрудниках — объектах класса Man, многих отделов какой-то организации. В примере мы возьмем только два отдела (100 и 115). Так как мы хотим быстро получать информацию о сотрудниках, то выбираем в качестве структуры для хранения данных в памяти хешированный ассоциативный контейнер. Очевидно, что если в качестве ключевого поля для него выбрать номер отдела, то поле не будет уникальным. Этот факт окончательно определяет выбор типа контейнера— hash_multimap.

Вы также, вероятно, помните, что все контейнеры типа тар — это Pair Associative контейнеры, так как они хранят пары типа pair<const Key, Data>. В нашем случае этой парой является pair<int, Man>, где первый элемент задает номер отдела, а второй сотрудника этого отдела. Для удобства пользования контейнером введем новые типы данных:

//======= ManPair - это тип используемых пар

typedef pair <int, Man> ManPair;

//======= ManMap - это тип контейнера

typedef hash_multimap <int, Man> ManMap;

//======= ManMapIt — это тип итератора

typedef ManMap::const_iterator ManMapIt;

Отметьте, что мы выбрали самый простой способ определения контейнера. Более точным описанием, которое намекает вам на возможность усложнения структуры, будет:

typedef hash_multimap <int, Man,

hash_compare <int, less<int> > > ManMap;

Отсюда ясно, что можно изменить предикат, по которому производится сравнение элементов контейнера. Для выбора всех сотрудников определенного отдела мы собираемся использовать метод:

equal_range(int /*Номер отдела*/);





который возвращает пару итераторов. Первый итератор пары указывает на начало диапазона внутри контейнера из сотрудников указанного отдела, а второй — на конец этого диапазона. Теперь пора в бой. Надо писать код, реализующий работу контейнера.

void main( )

{

typedef pair <int, Man> ManPair;

typedef hash_multimap <int, Man> ManMap;

typedef ManMap::const_iterator ManMapIt;

//====== Создаем пустой контейнер типа hash_multimap ManMap h;

//====== Наполняем его сотрудниками

h.insert (ManPair (100, тагу));

h.insert (ManPair (115, joe));

h.insert (ManPair (100, win));

h.insert (ManPair (100, charlie));

h.insert (ManPair (115, liza));

h.insert TManPair (115, joy));

//====== При выводе пользуемся парой

cout « "Contents of Hash Multimap\n\n";

for (ManMapIt p = h.begin();

p != h.end(); p++)

cout « "\n" « p->first

«". " « p->second;

//====== Выбираем диапазон (сотрудники 100-го отдела)

pair<ManMap!t, ManMapIt> pp = h.equal_range(100);

//====== Вновь пользуемся парой

cout « "\n\nEmployees of 100 department\n\n";

for (p = pp.first; p != pp.second; ++p)

cout « "\n" « p->first

«"." « p->second; cout « "\n\n";

}

He лишнее напомнить, что приведенный код надо дополнить объявлениями объектов класса Man и вставкой директивы #include <hash_map>. Директивы должны копиться. Я надеюсь, что с этой задачей вы справитесь самостоятельно. Объявления людей мы приводили где-то в начале урока. Программа должна произвести такой вывод:

Contents of Hash Multimap

115. Liza Dale, Age: 17

115. Joy Amore, Age: 18

115. Joe Doe, Age: 30

100. Winton Kelly, Age: 50

100. Charlie Parker, Age: 60

100. Mary Poppins, Age: 36

Employees of 100 department

100. Winton Kelly, Age: 50

100. Charlie Parker, Age: 60

100. Mary Poppins, Age: 36




Содержание раздела