Skip to main content

C++ STL

map / multimap / unordered_map

Complete lesson for map / multimap / unordered_map using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with C++ OOP and STL where relevant.

L1

Basics — map / multimap / unordered_map

Section: C++ STL. C++ map family — map, multimap, unordered_map with real-life examples and comparisons.

What is a map family?

  • **Map-like** containers store **key → value** associations.
  • map — **unique** keys, always **sorted** by key (balanced tree).
  • multimap — **duplicate keys allowed**, still **sorted** by key.
  • unordered_map — **unique** keys via **hashing** (no sorted order).
  • Headers: #include and #include .
  • **Real-life:** phone book (name → number) with map; one student → many marks with multimap; shopping-cart item counts with unordered_map.
IdeaMeaning
Key → valueEach entry links a key to a mapped value
Unique vs multimap/unordered_map one value per key; multimap many
OrderTree maps sorted by key; hash map unordered
LookupTree O(log n); hash avg O(1)
[]On map/unordered_map: may **insert** default if missing

Why use map / multimap / unordered_map?

  • Natural model for dictionaries, indexes, counters, and caches.
  • Tree maps give sorted-by-key reports “for free”.
  • Hash maps shine for fast lookup when order does not matter.
BenefitWhat you gain
AssociationStore data under a meaningful key
Sorted keysmap/multimap iterate ascending by key
Fast dictionaryunordered_map average O(1) access
Multi-indexmultimap one key → many records
Countersm[key]++ pattern for frequencies

Which map container?

  • Pick by **duplicate keys**, **order**, and **speed**.
ContainerDuplicate keys?OrderTypical costHeaderReal-life pick
mapNoSorted by keyO(log n)Phone book, sorted roster
multimapYesSorted by keyO(log n)Student → many scores
unordered_mapNoHash orderAvg O(1)Word counts, caches

Differences between map, multimap, unordered_map

  • Same “dictionary” idea — different uniqueness and ordering contracts.
Featuremapmultimapunordered_map
Duplicate keysNoYesNo
OrderSorted by keySorted by keyUnspecified
StructureTreeTreeHash table
insert/findO(log n)O(log n)Avg O(1)
operator[]Yes (may insert)NoYes (may insert)
at(k)Yes (throws)NoYes (throws)
Many values/keyUse nested containerNativeUse nested container
Real-lifeName → phoneName → marks listSKU → stock count

map vs set (quick)

  • set stores **keys only**; map stores **key → value**.
  • **Real-life:** guest list of IDs → set; guest ID → seat number → map.
NeedUse
Only membership / unique keysset / unordered_set
Key with associated datamap / unordered_map
Sorted unique keys, no payloadset
Sorted unique keys + payloadmap

map — unique sorted keys

  • Keys are **unique** and **sorted**; each key maps to one value.
  • operator[] **inserts** a default value if the key is missing.
  • Prefer find / at when you must not insert accidentally (at throws if missing).
  • **Real-life:** phone book (name → number); employee ID → salary in ID order; country code → capital.
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> ages;
    ages["Ann"] = 20;
    ages.insert({"Bob", 22});
    cout << ages["Ann"] << "\n";
    if (ages.find("Zoe") == ages.end()) cout << "missing\n";
    return 0;
}

multimap — duplicate keys allowed

  • Same key can appear **many times** with different values.
  • **No** operator[] — use insert and equal_range to read all values for a key.
  • Useful for indexes: one category → many items.
  • **Real-life:** student name → multiple course scores; department → many employees; tag → many blog posts.
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    multimap<string, int> scores;
    scores.insert({"Ali", 90});
    scores.insert({"Ali", 85});
    auto [lo, hi] = scores.equal_range("Ali");
    for (auto it = lo; it != hi; ++it)
        cout << it->second << " ";
    cout << "\n";
    return 0;
}

unordered_map — unique hashed keys

  • Unique keys; **not sorted** — ideal for dictionaries and counters.
  • Average **O(1)** lookup; [] inserts a default if missing.
  • reserve(n) can reduce rehashing when size is known.
  • **Real-life:** word frequency in a document; product SKU → price lookup; session token → user data cache.
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<string, int> cnt;
    cnt["apple"]++;
    cnt["apple"]++;
    cnt["banana"]++;
    cout << cnt["apple"] << "\n"; // 2
    return 0;
}

Common patterns

  • Iterate: for (auto& [k, v] : m) (C++17 structured bindings).
  • Check before insert: if (m.find(k) == m.end()) ….
  • Counters: unordered_map + m[key]++ is a classic interview pattern.
NeedPrefer
Sorted unique key→valuemap
One key, many values (sorted)multimap
Fast dictionary / counterunordered_map
Must not auto-insert on missfind / at (not [])

Real-life examples by container

  • Map everyday problems to the right map type.
Real-life situationBest fitWhy
Phone book: name → number, A–Z printoutmapUnique keys + sorted names
Employee ID → salary report by IDmapSorted unique IDs
Country → capital dictionarymapOrdered lookup / display
Student → several exam marksmultimapSame name, many values
Genre → many movie titlesmultimapOne key, many records
Hotel room type → many room numbersmultimapCategory index
Word frequency in a chat logunordered_mapFast counter, order unused
Shopping cart: SKU → quantityunordered_mapFast update by key
Browser cache: URL → page bytesunordered_mapO(1) get/put
Config flag → on/off valueunordered_map or mapHash if speed; map if sorted dump

Map family applications

  • Maps appear whenever you look up or update data by a key.
ApplicationContainerHow it helps
Dictionary / phone bookmapKey → value, sorted report
Frequency countingunordered_mapm[k]++ in average O(1)
Caching / memoizationunordered_mapStore computed results by input
Symbol table (compilers)map / unordered_mapName → type/address
Inverted index (tag → posts)multimapOne tag, many post IDs
Graph adjacency (node → weight)map or nestedNeighbor keyed maps
Histogram / bin countsunordered_mapBin label → count
Localization: key → translated stringunordered_mapFast message lookup
Inventory: product → stockunordered_mapUpdate quantity by SKU
Leaderboard by unique player IDmapID → score, sorted IDs

Application — phone book (map)

  • **Real-life:** store contacts; print alphabetically by name.
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, string> phone;
    phone["Ann"] = "555-0101";
    phone["Bob"] = "555-0199";
    phone["Ann"] = "555-0111"; // updates unique key
    for (auto& [name, num] : phone)
        cout << name << " -> " << num << "\n";
    return 0;
}

Application — student marks index (multimap)

  • **Real-life:** one student takes several tests; list all marks for that name.
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    multimap<string, int> marks;
    marks.insert({"Ali", 90});
    marks.insert({"Ali", 85});
    marks.insert({"Bea", 88});
    auto [lo, hi] = marks.equal_range("Ali");
    cout << "Ali: ";
    for (auto it = lo; it != hi; ++it) cout << it->second << " ";
    cout << "\n";
    return 0;
}

Application — word counter (unordered_map)

  • **Real-life:** count how often each word appears in a message.
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<string, int> freq;
    for (string w : {"hi", "hi", "bye", "hi"}) freq[w]++;
    for (auto& [w, n] : freq) cout << w << " " << n << "\n";
    return 0;
}

When to use which

  • Need ordered keys or range queries by key order → **map**.
  • Need many values per key in order → **multimap**.
  • Need speed and uniqueness, order irrelevant → **unordered_map**.
  • **Real-life rule of thumb:** alphabetical directory → map; one person many records → multimap; cart/cache/counter → unordered_map.

Key points to remember

  • map = unique + sorted; multimap = duplicates + sorted; unordered_map = unique + hash.
  • m[k] may **insert** a default — use find/at when that is unwanted.
  • multimap has **no** operator[].
  • set = keys only; map = key → value.
  • Real-life: phone book → map; marks index → multimap; word counts → unordered_map.
L2

Advanced — map / multimap / unordered_map

[] vs insert vs at

  • m[k] creates a default value if k is new (map / unordered_map).
  • insert does not overwrite an existing unique key.
  • at(k) throws out_of_range if missing — never inserts.
  • multimap has no [] / at for a single value.
  • **Real-life pitfall:** checking if (phone["Zoe"]) silently adds Zoe with an empty/default number.

Application — shopping cart (unordered_map)

  • **Real-life:** SKU → quantity; increment when user adds an item.
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<string, int> cart;
    auto add = [&](const string& sku, int n = 1) { cart[sku] += n; };
    add("TEA");
    add("TEA");
    add("MUG", 2);
    for (auto& [sku, qty] : cart)
        cout << sku << " x" << qty << "\n";
    return 0;
}

Application — config / cache idea

  • Store setting → value or key → cached result in unordered_map.
  • **Real-life:** feature flags; memoize expensive API results by request id.

Iteration and order

  • map / multimap iterate keys in sorted order.
  • unordered_map iteration order is unspecified and can change after rehash.
  • **Real-life:** print directory A–Z with map; do not rely on hash order for a report.

Complexity & hashing

  • Tree maps: O(log n) per lookup.
  • Hash maps: average O(1); custom key types need hash + equality.
  • reserve on unordered_map when you know approximate size.

Design tips

  • Need sorted keys → map/multimap; only fast lookup → unordered_map.
  • Many values per key → multimap or map>.
  • Never use [] just to test presence.
  • Prefer structured bindings: for (auto& [k, v] : m).
  • Document real-life meaning of key and value (ID, price, count).
L3

Tricky Interview Points

Q1) map vs unordered_map?

Answer map is ordered (tree, O(log n)); unordered_map is hashed (average O(1)) with no sorted order.

Q2) map vs multimap?

Answer map requires unique keys; multimap allows duplicate keys, each with a value.

Q3) What does map operator[] do if the key is missing?

Answer It default-constructs a value for that key and inserts it, then returns a reference.

Q4) Why is there no operator[] on multimap?

Answer A key can map to many values, so a single reference result would be ambiguous.

Q5) Best container for a frequency counter?

Answer unordered_map is usual for word/int counts when order does not matter.

Q6) Give a real-life example for map.

Answer Phone book name→number; employee ID→salary printed in ID order.

Q7) Give a real-life example for multimap.

Answer Student name→several exam marks; genre→many movie titles.

Q8) Give a real-life example for unordered_map.

Answer Word frequency; shopping cart SKU→qty; URL→cached page.

Q9) map vs set?

Answer set stores keys only; map stores key→value pairs.

Q10) How do you read all values for one key in multimap?

Answer equal_range(key) and iterate [first, second).

Q11) insert vs operator[] on map?

Answer insert does not overwrite an existing key; [] assigns and may insert a default first.

Q12) When prefer map over unordered_map?

Answer When you need sorted keys, ordered traversal, or ordered range queries.

L4

Simple Programs

map — ages dictionary

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

int main() {
    map<string, int> ages{{"Ann", 20}, {"Bob", 22}};
    for (auto& [name, age] : ages)
        cout << name << " " << age << "\n";
    return 0;
}

multimap — multiple scores

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

int main() {
    multimap<string, int> m;
    m.insert({"Ali", 90});
    m.insert({"Ali", 70});
    m.insert({"Bea", 88});
    for (auto& [k, v] : m) cout << k << ":" << v << "\n";
    return 0;
}

unordered_map — word count

#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<string, int> freq;
    for (string w : {"a", "b", "a", "c", "b", "a"}) freq[w]++;
    for (auto& [w, n] : freq) cout << w << " " << n << "\n";
    return 0;
}

Real-life — phone book (map)

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

int main() {
    map<string, string> book{{"Ann", "111"}, {"Bob", "222"}};
    cout << book.at("Ann") << "\n";
    if (book.find("Zoe") == book.end()) cout << "no Zoe\n";
    return 0;
}

Real-life — department staff (multimap)

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

int main() {
    multimap<string, string> dept;
    dept.insert({"HR", "Ada"});
    dept.insert({"HR", "Ben"});
    dept.insert({"IT", "Cara"});
    auto [lo, hi] = dept.equal_range("HR");
    for (auto it = lo; it != hi; ++it) cout << it->second << " ";
    cout << "\n";
    return 0;
}

Real-life — cart quantities (unordered_map)

#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;

int main() {
    unordered_map<string, int> cart;
    cart["milk"] += 1;
    cart["eggs"] += 12;
    cart["milk"] += 1;
    cout << "milk " << cart["milk"] << "\n";
    return 0;
}
L5

Problem Solving Tricks

  • map = unique + sorted; multimap = duplicates + sorted; unordered_map = unique + hash.
  • m[k] may insert — use find/at when that is unwanted.
  • multimap has no operator[].
  • unordered_map is the usual frequency-counter tool.
  • Iterate map/multimap for sorted keys.
  • Reserve unordered_map when you know approximate size.
  • Real-life: phone book → map; marks/tags index → multimap; cart/cache → unordered_map.
  • set = keys only; map = key → value.
  • equal_range is the multimap “all values for this key” tool.
  • Structured bindings: for (auto& [k, v] : m).
  • Prefer at() when missing keys should be errors.
  • Document what key and value mean in the real problem.
L6

Practice Programs List

  1. Build a map of names to ages; print in sorted name order.
  2. Use multimap to store two scores for the same student; print equal_range.
  3. Count word frequencies with unordered_map.
  4. Show that ages["Zoe"] inserts 0 into a map of int values.
  5. Write a choose-table for map vs multimap vs unordered_map.
  6. Model a phone book; update one number; print A–Z.
  7. Model department → employees with multimap; list one department.
  8. Model a shopping cart SKU→qty; add the same SKU twice.
  9. List 8 real-life examples and pick the best map container for each.
  10. Explain a bug caused by using [] only to “check” a key.
  11. Rewrite a frequency counter using find + insert instead of [].
  12. Compare map vs set for “ID only” vs “ID → seat number”.