map și
unordered_map din STL
Un map este un dicționar:
asociază chei cu valori.
Fiecare cheie e unică și are exact o valoare asociată. Cheile
sunt mereu sortate.
#include <map>map<K, V>
map<string, int> varsta;
varsta["Ana"] = 15;
varsta["Mihai"] = 16;
varsta["Elena"] = 14;
cout << varsta["Ana"]; // 15
cout << varsta["Mihai"]; // 16
cout << varsta.size(); // 3Operații
| Operație | Ce face | Complexitate |
|---|---|---|
m[key] = val |
Inserează sau actualizează | O(log n) |
m[key] |
Acces valoare (creează dacă nu există!) | O(log n) |
m.count(key) |
1 dacă există, 0 dacă nu | O(log n) |
m.find(key) |
Iterator la pereche (sau end()) |
O(log n) |
m.erase(key) |
Șterge perechea | O(log n) |
m.size() |
Număr perechi | O(1) |
m.empty() |
Verifică gol | O(1) |
Iterare prin map
Elementele sunt sortate după cheie:
map<string, int> m;
m["banana"] = 3;
m["mar"] = 7;
m["apa"] = 1;
for (auto &p : m)
cout << p.first << " = " << p.second << endl;Output:
apa = 1
banana = 3
mar = 7p.first = cheia, p.second =
valoarea.
Frecvența cuvintelor
#include <fstream>
#include <map>
#include <cstring>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int main()
{
char s[1001];
fin.getline(s, 1001);
map<string, int> fr;
char *p = strtok(s, " ");
while (p != NULL) {
fr[p]++;
p = strtok(NULL, " ");
}
for (auto &pereche : fr)
fout << pereche.first << ": " << pereche.second << endl;
return 0;
}date.in:
ana are ana mere anadate.out:
ana: 3
are: 1
mere: 1fr[p]++ funcționează pentru că
m[key] creează automat intrarea cu valoarea 0 dacă
nu există, apoi o incrementează.
Verificare existență
map<string, int> m;
m["test"] = 5;
// Varianta 1: count
if (m.count("test"))
cout << "Exista";
// Varianta 2: find
auto it = m.find("test");
if (it != m.end())
cout << it->second; // 5
// ATENȚIE: m["inexistent"] CREEAZĂ intrarea cu valoarea 0!
cout << m["inexistent"]; // 0, dar acum "inexistent" există în map!Nu folosi m[key] pentru
verificare! Dacă cheia nu există, o creează automat cu
valoare 0. Folosește m.count(key) sau
m.find(key).
map cu chei
numerice
Funcționează ca un vector de frecvență dar pentru valori oricât de mari:
map<int, int> fr;
fr[1000000000]++; // funcționează! Nu ai nevoie de vector de 10^9
fr[999999999]++;
fr[1000000000]++;
cout << fr[1000000000]; // 2Când map
vs vector de frecvență?
| Vector de frecvență | map<int, int> |
|
|---|---|---|
| Valori 0 - 10^6 | Da (6 MB) | Da |
| Valori 0 - 10^9 | Nu (prea mare) | Da |
| Valori negative | Nu | Da |
| Complexitate acces | O(1) | O(log n) |
| Memorie | Fixă (chiar dacă puține valori) | Proporțională cu nr. de valori distincte |
unordered_map<K, V>
Varianta neordonată - nu sortează cheile, dar operațiile sunt O(1) în medie (în loc de O(log n)).
#include <unordered_map>
unordered_map<string, int> m;
m["test"] = 5;
cout << m["test"]; // 5 - aceleași operații, dar mai rapidComparație
map |
unordered_map |
|
|---|---|---|
| Ordine | Sortată după cheie | Fără ordine |
| Insert/Find | O(log n) | O(1) mediu |
| Iterare | În ordine | Ordine aleatorie |
| Include | <map> |
<unordered_map> |
| Cel mai rău caz | O(log n) | O(n) (coliziuni) |
Folosește map când ai nevoie de ordine sau
lower_bound/upper_bound. Folosește
unordered_map când vrei viteză pură.
Exemplu: prima apariție a fiecărui element
#include <fstream>
#include <map>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int main()
{
int n;
fin >> n;
map<int, int> prima; // valoare -> prima poziție
for (int i = 1; i <= n; i++) {
int x;
fin >> x;
if (prima.count(x) == 0)
prima[x] = i;
}
for (auto &p : prima)
fout << p.first << " apare prima data la pozitia " << p.second << endl;
return 0;
}map cu
lower_bound / upper_bound
La fel ca la set:
map<int, string> m;
m[10] = "zece";
m[20] = "douazeci";
m[30] = "treizeci";
auto it = m.lower_bound(15); // primul cu cheia >= 15
cout << it->first << " " << it->second; // 20 douazeciGreșeli frecvente
1. m[key] creează
intrarea
map<int, int> m;
cout << m[5]; // 0, DAR acum m conține {5: 0}!
cout << m.size(); // 1, nu 0!Folosește count sau find pentru
verificare.
2. Iterare cu modificare
La fel ca la set, nu modifica map-ul în timp ce iterezi cu iteratori.
3. Confuzia map cu
set
set<int>: mulțime de valorimap<int, int>: perechi cheie-valoare
set stochează valori,
map stochează perechi.
Ce să reții
map<K, V>: dicționar sortat, cheie-valoare, O(log n) per operație.m[key]accesează SAU creează.m.count(key)verifică fără a crea.unordered_map: nesortată, O(1) mediu, mai rapidă dar fără ordine.- Ideal pentru: frecvențe cu valori mari, asocieri cheie-valoare, înlocuire vector de frecvență.
- Iterarea prin
mape în ordinea crescătoare a cheilor. lower_bound/upper_boundfuncționează ca laset.