C++. Класс map. Ассоциативный контейнер

Класс map. Ассоциативный контейнер. Создание контейнера. Конструкторы. Создание пары. Обзор функций и операторов класса


Содержание


Поиск на других ресурсах:

 
1. Общие сведения о классе map. Объявление класса

Класс map представляет собой ассоциативный контейнер или хэш-таблицу. Ассоциативный контейнер map представляет собой набор элементов, каждый из которых представлен в виде пар ключ:значение (key: value). Ключ является именем, с помощью которого можно получить необходимое значение. Другими словами, доступ к значению осуществляется с помощью ключа. Между ключом и значением устанавливается связь (ассоциация).

Все ключи в ассоциативном контейнере map уникальны (повторение ключей не допускается). Если необходимо обеспечить повторяемость ключей, то для этого используется другой класс multimap.

Чтобы использовать возможности класса map, нужно подключить заголовок <map>

#include <map>

Согласно документации объявления шаблонной формы класса map следующее

template <class Key, class T, class Comp = less<Key>,
    class Allocator = allocator<pair<const key, T> class map

здесь

  • Key – класс, определяющий тип ключа;
  • T – тип данных (значений), получаемых по ключу типа Key;
  • Comp – функция, позволяющая сравнивать два ключа. По умолчанию в функции Comp() используется стандартный функтор less;
  • Allocator – класс, выступающий в качестве распределителя памяти. По умолчанию выступает обычный класс allocator.

 

2. Конструкторы класса map. Создание ассоциативного контейнера

Класс map имеет несколько конструкторов.

Конструктор создающий пустой массив имеет следующий вид

explicit map(const Comp &compare_func = Comp(),
    const Allocator &alloc = Allocator());

Конструктор создающий ассоциативный контейнер на основе объекта obj, который является тоже типа map

map(const map<Key, T, Comp, Allocator> &obj);

Конструктор, создающий ассоциативный массив, содержащийся из элементов заданного диапазона

template <class InIterator>
list(InIterator start, InIterator end, const Comp &compare_func = Comp(), const Allocator &a = Allocator());

Во всех трех вышеприведенных конструкторах используются следующие обозначения:

  • start, end – итераторы, задающие начало и конец диапазона;
  • compare_func – функция, определяющая порядок следования элементов массива.

Пример.

В примере создается ассоциативный массив пар, в которых ключ (key) является типом int, а значение (value) является типом string. Для создания массива используются разные способы (конструкторы).

#include <iostream>
#include <map>
using namespace std;

void main()
{
  // Конструкторы класса map.
  // Конструктор 1. Создать пустой массив пар int:string
  map<int, string> m1;
  m1.insert(pair<int, string>(1, "One")); // добавить пару 1:"One"
  m1.insert(pair<int, string>(2, "Two")); // добавить пару 2:"Two"
  m1.insert(pair<int, string>(4, "Four")); // добавить пару 4:"Four"
  m1.insert(pair<int, string>(5, "Five")); // добавить пару 5:"Five"

  // Конструктор 2. Создать другой массив на основе существующего
  map<int, string> m2(m1);
  cout << m2.at(2) << endl; // Two
  cout << m2.at(4) << endl; // Four

  // Конструктор 3. Создать массив на основе итераторов
  // Взять диапазон позиций [0; 1] включительно (позиции нумеруются с 0)
  // 3.1. Объявить итераторы
  map<int, string>::iterator it_start;
  map<int, string>::iterator it_end;

  // 3.2. Установить итератор it_start на первый элемент массива m1.
  it_start = m1.begin();

  // 3.3. Установить итератор it_end за элементом с индексом 1
  it_end = m1.begin();

  // 3.4. Перемотать итератор на 2 позиции (за позицию с индексом 1)
  for (int i = 0; i < 2; i++)
    it_end++;

  // 3.5. Создать массив m3 на основании массива m1
  map<int, string> m3(it_start, it_end);

  // 3.6. Вывести массив m3
  map<int, string>::iterator it = m3.begin();
  cout << "Array m3:" << endl;
  while (it != m3.end())
  {
    cout << it->first << " : " << it->second << endl;
    it++;
  }
  cout << "--------------------" << endl;
}

Результат

Two
Four
Array m3:
1 : One
2 : Two
--------------------

 

3. Функции класса map. Обзор

Класс map имеет следующие основные функции:

  • at() – возвращает значение по известному ключу;
  • begin() – возвращает итератор на первый элемент контейнера;
  • clear() – удаляет из массива все элементы;
  • count() – возвращает количество дубликатов элементов для заданного ключа;
  • empty() – определяет, пуст ли ассоциативный массив (не содержит ни одного элемента);
  • end() – возвращает итератор, установленный по последнему элементу контейнера;
  • erase() – удаляет элемент из ассоциативного контейнера;
  • find() – возвращает итератор, установленный на заданный ключ;
  • insert() – добавляет в контейнер новую пару;
  • max_size() – возвращает размер, фактически выделенный для ассоциативного контейнера с учетом его дальнейшего роста;
  • size() – возвращает текущее количество элементов (размер) в ассоциативном контейнере;
  • swap() – обменивает местами содержимое двух контейнеров;
  • operator=() – присваивает один контейнер другому;
  • operator[]() – возвращает значение (value) по заданному ключу.

 

4. Операторы сравнения класса map. Обзор. Примеры

В классе map определены операторы сравнения: ==, !=, <=, >=, <, >.

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

В операторах <, >, <=, >= сравнение происходит в следующем порядке:

  1. Сначала сравниваются ключи контейнеров в порядке с первого до последнего. Это означает, что ключ первого контейнера сравнивается с ключом второго контейнера. Первое несовпадение в ключах установит подходящий результат.
  2. Если соответствующие ключи контейнеров совпадают, следующими сравниваются значения в порядке с первого до последнего. Значения последовательно просматриваются и сравниваются.
  3. Если и ключи и значения совпадают до какой-то пары, то сравниваются длины контейнеров.

Пример 1. Сравнение на равенство и неравенство.

...

// Операторы сравнения
// 1. Сравнение идентичных ассоциативных контейнеров
map<int, string> m1;
m1.insert(make_pair(5, "Five"));

map<int, string> m2;
m2.insert(make_pair(5, "Five"));

bool res = m1 == m2; // res = true
res = m1 != m2; // res = false

// 2. Сравнение контейнеров в которых отличается значение
map<int, string> m3, m4;
m3.insert(make_pair(4, "Four"));
m4.insert(make_pair(4, "4"));
res = m3 == m4; // res = false
res = m3 != m4; // res = true

// 3. Сравнение контейнеров, в которых отличаются ключи
map<int, string> m5, m6;
m5.insert(make_pair(6, "Six"));
m6.insert(make_pair(7, "Six"));
res = m3 == m4; // res = false
res = m3 != m4; // res = true
cout << res << endl;

...

Пример 2. Сравнение на больше/меньше.

...

// Операторы сравнения
// 1. Сравнение >, >= контейнеры равны
map<int, string> m1;
m1.insert(make_pair(5, "Five"));

map<int, string> m2;
m2.insert(make_pair(5, "Five"));

bool res = m1 > m2; // res = false
res = m1 >= m2;   // res = true

// 2. Сравнение >, >=, <, <= - ключ первого контейнера больше ключа второго
map<int, string> m3, m4;
m3.insert(make_pair(1, "One"));
m4.insert(make_pair(0, "Zero"));
res = m3 > m4; // res = true
res = m3 >= m4; // res = true
res = m3 < m4; // res = false
res = m3 <= m4; // res = false

// 3. Ключи равны, отличаются значения,
//     сначала сравниваются ключи, затем значения
map<int, string> m5, m6;
m5.insert(make_pair(1, "AAA"));
m6.insert(make_pair(1, "ABC"));
res = m5 > m6; // res = false
res = m5 >= m6; // res = false
res = m5 < m6; // res = true
res = m5 <= m6; // res = true

// 4. Длины контейнеров разные,
//     первые пары key:value совпадают
map<int, string> m7, m8;
m7.insert(make_pair(1, "One"));
m7.insert(make_pair(2, "Two"));
m8.insert(make_pair(1, "One"));
res = m7 > m8; // res = true - берется к вниманию длина контейнеров
res = m7 >= m8; // res = true
res = m7 < m8; // res = false
res = m7 <= m8; // res = false

// 5. Длина первого контейнера больше за длину второго,
//    однако первый ключ первого контейнера меньше первого ключа второго.
map<int, string> m9, m10;
m9.insert(make_pair(1, "One"));
m9.insert(make_pair(2, "Two"));
m10.insert(make_pair(2, "Two"));
res = m9 > m10; // res = false
res = m9 >= m10; // res = false
res = m9 < m10; // res = true
res = m9 <= m10; // res = true

...

 

5. Структура pair<Key, Value>

Чтобы создать пару ключ:значение (key:value), нужно использовать структуру pair, которая имеет следующее шаблонное объявление

template <class Ktype, class Vtype>
struct pair
{
  typedef Ktype first_type;
  typedef Vtype second_type;
  Ktype first;
  Vtype second;
}

здесь

  • Ktype – тип ключа;
  • Vtype – тип значения;
  • first – ключ;
  • second – значение.

После создания пара типа pair<Key, Value> может быть добавлена в ассоциативный контейнер с помощью метода insert().

Экземпляр типа структуры pair создается разными способами с использованием соответствующих конструкторов. Ниже приведены некоторые основные способы создания пары ключ:значение.

 

5.1. Создание пары key:value. Использование структуры first, second

В структуре pair<Key, Value> есть поля, которые дают непосредственный доступ к ключу и значению:

  • first – определяет ключ;
  • second – определяет значение.

В наиболее общем случае создание пары с заполнением полей first, second выглядит следующим образом

// Создание объекта пары
pair<K, V> p;

// Заполнение значений
p.first = key;
p.second = value;

здесь

  • K, V – тип ключа и тип значения;
  • key – значение ключа типа K;
  • value – значение, связываемое с ключом K.

Пример.

...

// Использование полей first, second структуры pair<K, V>
// 1. Создать пару типов double, float и вывести ее на экран
pair<double, float> p;
p.first = 2.5;
p.second = 100.55f;
cout << p.first << " : " << p.second << endl;

// 2. Создать пару типов char:string и вывести ее на экран
pair<char, string> season;
season.first = 'W';
season.second = "Winter";
cout << p.first << " : " << p.second << endl;

...

 

5.2. Создание пары key:value с помощью конструктора

Экземпляр структуры pair<Key, Value> может быть создан с помощью соответствующего конструктора по следующей форме

pair<K, V> objP(key, value);

здесь

  • K, V – тип ключа и тип значения;
  • key, value – конкретные значения ключа и значения.

Пример.

...

// Создание пары с помощью конструктора pair(K, V)
// 1. Создать пару типов char, int
pair<char, int> p1('H', 16);
cout << p1.first << " : " << p1.second << endl; // 'H' : 16

// 2. Создать пару типов bool, string
pair<bool, string> p2(true, "True");
cout << p2.first << " : " << p2.second << endl; // 1 : True

...

 

5.3. Создание пары key:value на основе другой пары

Если нужно получить экземпляр структуры pair<Key, Value> из другой пары, тогда используется следующая форма

pair<K, V> p2(p1);

здесь

  • p1 – экземпляр-оригинал. Значения first, second этого экземпляра копируются в экземпляр p2;
  • p2 – экземпляр-копия. Ключ (first) и значение (second) p2 заполняются из экземпляра p1.

Пример.

...

// Создание пары с другой пары
// 1. Создать пару типов char, int
pair<char, int> p1('H', 16);

// 2. Получить другую пару
pair<char, int> p2(p1);
cout << p2.first << " : " << p2.second << endl; // H : 16

...

 

5.4. Создание пары с помощью функции make_pair()

Пара типа pair<Key, Value> можно создать с помощью функции make_pair(), которая согласно документации имеет следующий прототип

template <class Ktype, class Vtype>
pair<Ktype, Vtype> make_pair(const Ktype &k, const Vtype &v);

здесь

  • Ktype – тип ключа;
  • Vtype – тип значения.

Удобство использования метода make_pair() заключается в том, что типы объектов (ключа и пара) определяются компилятором автоматически.

Пример.

...

// Создание пары методом make_pair()
// 1. Создать пару типа int:string
pair<int, string> p1;
p1 = make_pair(2, "Two");

// 2. Создать пару типа char:int и добавить ее в ассоциативный контейнер
pair<char, int> p2 = make_pair('B', 2);
map<char, int> m1;
m1.insert(p2);

// 3. Создать пару, в которой тип определяется автоматически и добавить ее в контейнер
m1.insert(make_pair('O', 8));

...

 


Связанные темы