map в C++

Map в C++: что это и как с этим работать

В данном уроке мы разберем еще один часто используемый контейнер STL — map.

Что такое map

Это ассоциативный контейнер, который работает по принципу — [ключ — значение]. Он схож по своему применению с вектором и массивом, но есть некоторые различия:

  1. Ключом может быть все что угодна. От обычной переменной до класса.
  2. При добавлении нового элемента контейнер будет отсортирован по возрастанию.
map ключ c++

Мы можем создать ключ из любых компонентов и он будет — рабочим.

Поэтому можно с легкостью сделать словарь:

  • Ключом в нашем случае будет — русское слова.
  • А значением — английское.

Добавление, удаление, обращение к элементам происходит за log n. n — в нашем случае размер контейнера.

Как создать map

Сперва понадобится подключить соответствующую библиотеку:

Чтобы создать map нужно воспользоваться данной конструкцией:

  • <L> — этот тип данных будет относиться к значению ключа.
  • <R> — этот тип данных соответственно относится к значению.

В нашем случае:

  • Ключ — строка.
  • Значение — число.

При создании map все его элементы будут иметь значение нуля.

Также имеется возможность добавить значения при инициализации (С++ 11 и выше):

Итераторы для map

Использование итераторов одна из главных тем, если вам понадобится оперировать с этим контейнером. Создание итератора, как обычно происходит так:

  • <тип данных><string, int> например.

С помощью его можно использовать две операции (it — итератор):

  1. Чтобы обратится к ключу нужно сделать так: it->first.
  2. Чтобы обратится к значению ячейки нужно сделать так: it->second.

Нельзя обращением к ключу (...->first) изменять его значение, а вот изменять таким образом значение ячейки (...->second) легко.

Нельзя использовать никакие арифметические операции над итератором:

Все это будет считаться еще одной ошибкой для компилятора.

Для увеличения или уменьшения можно использовать инкремент или декремент.

Нельзя делать то же самое используя операцию присваивания (it += 1) или вычитания (it -= 1).

Чтобы не писать циклы для увеличения итератора на большие значения, можно воспользоваться функцией advance():

Она сдвигает указанный итератор вниз или вверх на указанное количество ячеек. В нашем случае он сначала увеличит на 7, а потом уменьшит на 5, в итоге получится сдвиг на две вверх.

Вывод контейнера

Давайте попробуем вывести все элементы, которые находятся в контейнере.

А вот рабочая программа:

cout_map.cpp
Введите количество элементов: 5
0) 33
1) 5
2) 2
3) 9
4) 27
А вот все отсортированно:
0) Ключ 2, значение 2
1) Ключ 5, значение 1
2) Ключ 9, значение 3
3) Ключ 27, значение 4
4) Ключ 33, значение 0
Process returned 0 (0x0) execution time : 0.010 s
Press any key to continue.

Методы map

Ниже мы разберем функции которые можно использовать для работы с map.

Некоторые функции не могут работать с map из-за его специфической архитектуры.

insert

Это функция вставки нового элемента.

  • num_1 — ключ.
  • num_2 — значение.

Мы можем сделать то же самое вот так:

count

Возвращает количество элементов с данным ключом. В нашем случае будет возвращать — 1 или 0.

Эта функция больше подходит для multimap, у которого таких значений может быть много.

Нужно помнить, что для строк нужно добавлять кавычки — count("Good").

find

У этой функции основная цель узнать, есть ли определенный ключ в контейнере.

  • Если он есть, то передать итератор на его местоположение.
  • Если его нет, то передать итератор на конец контейнера.

Например, давайте разберем данный код:

Давайте рассмотрим поподробнее:

  • В строке 8: мы создали map под названием — book.
  • В строке 9: задали единственный ключ "book" со значением "книга".
  • В строке 11: создали два итератора it и it_2.
  • В строке 13 — 14: получаем итератор на ключ «book» и выводим его значение.
  • В строке 16: получаем итератор на ключ «books», которого нет в нашем контейнере.
  • В строке 18 — 20: проверяем не указывает ли it_2 на конец контейнера и предупреждаем пользователя.

erase

Иногда приходится удалять элементы. Для этого у нас есть функция — erase().

Давайте посмотрим как она работает на примере:

passport в нашем случае хранит имя как ключ, а фамилию как значение.

В итоге мы уменьшим количество наших элементов на один.

Также здесь мы воспользовались функцией size(), которая возвращает количество элементов.

А вот вывод:

erase.cpp
Size: 3
Size: 2
Process returned 0 (0x0) execution time : 0.010 s
Press any key to continue.

Создаем простую игру

Давайте закрепим наши знания на практике — создав примитивную игру.

Пользователю понадобится ввести количество домов на улице и указать для каждого дома сколько людей там проживает.

Далее он может модифицировать данные об улице таким образом:

  • Введя 0 — он сможет узнать имеется ли такой дом и если да, то сколько там живет людей.
  • Введя 1 — сможет удалить ключ из контейнера навсегда.
  • Введя 2 — он сможет добавить новый дом.

Вот код:

Теперь давайте подробно разберем, что тут такое:

  1. В строках 13 — 18: считываем все дома и их жителей.
    • В строке 17: вместо обычного объявления ячейки мы использовали функцию insert.
  2. В строках 24 — 57: здесь находится основной блок и на него стоит обратить внимание.
  3. В строке 26: считываем операцию, которую хочет выполнить пользователь.
  4. В строках 29 — 38: находится код для выполнения операции 0 (вывод элемента).
    • В строке 31: оперируем функцией count, чтобы узнать имеется ли у нас данный элемент.
  5. В строках 39 — 49: находится блок кода для использования операции 1 (удаление).
    • В строке 42: проверяем есть ли этот вообще (даже если его нет, удаление не существующего элемента не приведет к ошибке).
    • Если он есть — удаляем.
  6. В строках 51 — 57: здесь выполнятся код для операции 2 (добавление).

А вот рабочая программа:

task_for_map.cpp
Введите количество домов на улице: 5
Укажите дом и сколько в нем живет людей:
0) Дом 1 64
1) Дом 2 81
2) Дом 3 100
3) Дом 4 25
4) Дом 5 121
Введите количество операций: 5
0) 0
Укажите номер дома: 1
Количество людей: 64
1) 1
Какой дом удалить: 1
Элемент удален!
2) 0
Укажите номер дома: 1
Такого дома не существует!
3) 2
Какой дом добавить: 7
Какое количество людей там проживает: 169
4) 1
Какой дом удалить: 9
Его нет в списке, возможно уже разрушен 🙂
Process returned 0 (0x0) execution time : 0.010 s
Press any key to continue.

Плюсы и минусы: использования map

Плюсы:

  • Ключом может быть любая переменная. Это огромный плюс, например если придется делать словарь.

Минусы:

  • Долгое добавление нового элемента.
  • Долгое обращение к элементу.
  • Долгое удаление нового элемента.
  • Также слишком затратный по памяти

Все эти операции происходят за — log n (n — это размер контейнера).

Подытожим:

  1. Если вам требуется быстрый отклик программы, то если возможно оперировать вектором либо массивом лучше использовать именно их.
  2. Если же время не стоит на первом месте, то можно им пренебречь и использовать map.

Упражнение

Создайте программу в которой пользователь сможет использовать данные операции:

  • Добавлять новое слова — [английское — русское].
  • Удалять их.
  • Изменять значение уже существующего слова (...->second).

Если есть вопросы пишите их в комментариях. Удачи в новых начинаниях!


1 комментарий к записи “Map в C++: что это и как с этим работать”

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

Ваш адрес email не будет опубликован.

  • Metod[]:

    #include
    #include

    using namespace std;

    class Vocabulary
    {
    private:
    map vocabulary;
    string m_num_1;
    string m_num_2;

    public:
    void fillingVocabulary(string num_1, string num_2)
    {
    m_num_1 = num_1;
    m_num_2 = num_2;
    vocabulary.insert(make_pair(num_1, num_2));
    }

    void printVocabulary()
    {
    map :: iterator it = vocabulary.begin();
    cout << "А вот все отсортированно: " << endl;
    for (int i = 0; it != vocabulary.end(); it++, i++)
    {
    cout << i << ") " <first << " — " <second << endl;
    }
    }

    void deleteWord(string word)
    {
    map :: iterator full_name; // создали итератор на passport

    full_name = vocabulary.find(word); // находим ячейку
    vocabulary.erase(full_name);
    }

    void renameTranslateWord(string word, string translation)
    {
    map :: iterator it;

    it = vocabulary.find(word);
    it->second = translation;

    if (it == vocabulary.end()) {
    cout << "Ключа со значением " << word << " нет!\n";
    }
    }
    };

    int main()
    {
    Vocabulary myVoc;
    myVoc.fillingVocabulary("go", "идти");
    myVoc.printVocabulary();

    myVoc.fillingVocabulary("Hello", "Привет");
    myVoc.printVocabulary();

    myVoc.deleteWord("go");
    myVoc.printVocabulary();

    myVoc.renameTranslateWord("Hello", "Пока");
    myVoc.printVocabulary();

    return 0;
    }