REČNIK PODATAKA - MAPE U C++
Mape u C++ su kolekcije podataka koje čuvaju podatke čijim vrednostima se pristupa pomoću jedinstvenog ključa. To je zapravo rečnik podataka i deklariše se na sledeći način:
map<tip_ključa,tip_vrednosti>naziv_mape;
map<tip_ključa,tip_vrednosti>naziv_mape;
Posmatrajmo sledeći problem:
Zadati imena grupe učenika u jednom odeljenju. Uneti njihove prosečne ocene na kraju školske godine. odrediti prosek grupe i odrediti koliko je učenika postiglo uspeh iznad prosečnog
Rešenje: Ovaj primer ćemo rešiti upotrebom mapa, tako što će se za ključ upotrebiti ime učenika, a kao vrdnost unutar mape smestiti njihov uspeh.
Da bi koristili mape u C++ unutar fajla mora se uključiti datoteka zaglavlja map:
Rešenje: Ovaj primer ćemo rešiti upotrebom mapa, tako što će se za ključ upotrebiti ime učenika, a kao vrdnost unutar mape smestiti njihov uspeh.
Da bi koristili mape u C++ unutar fajla mora se uključiti datoteka zaglavlja map:
#include < map >
Zatim je potrebno deklarisati mapu:
map < string, double> prosek;
Vidimo da će tipovi za ključeve biti string i to se odnosi na imena učenika, dok će tipovi vrednosti biti double, s obzirom da su vrednosti u stvari prosečne ocene, dakle, realni brojevi.
Inicijalizacija mape
Jedan od načina da mapu popunimo sa vrednostima je da je inicijalizujemo i to je slučaj kada unapred znamo podatke o učenicima, njihova imena i ostvarene uspehe, tj. njihove prosečne ocene na kraju godine.
prosek={
{"Mika",4.52},
{"Milica",4.78},
{"Nikola",3.89 }
};
{"Milica",4.78},
{"Nikola",3.89 }
Iteracije kroz mapu c++
U svakom ciklusu petlje se uzima sledeći par koji sadrži i ključ i vrednost(Ime učenika i prosek). Pristup ključu se ostvaruje pomoću atributa first, dok se pristup vrednosti ostvaruje pomoću atributa second.
//ispisivanje podataka smeštenih unutar mape
for(auto parKljucVrednost: prosek){
for(auto parKljucVrednost: prosek){
cout << parKljucVrednost.first << " " << parKljucVrednost.second << endl;
}Iteracija i štampanje elemenata mape
U C++ postoje dva osnovna načina za iteraciju kroz mapu: korišćenjem opsežne petlje (for) i upotrebom iteratora. Oba pristupa imaju svoje prednosti i primene, a u nastavku su njihove karakteristike i preporuke za upotrebu:
1. Opsežna for petlja (range-based for loop)
Ovaj pristup je intuitivan i čini kod preglednijim, naročito kada radite sa mapom koja ne zahteva modifikaciju elemenata tokom iteracije.
map<string, int> ucesnici = {{"Marko", 3}, {"Ana", 2}, {"Ivan", 1}};
for (const auto& par : ucesnici) {
cout << par.first << ": " << par.second << endl;
}
for (const auto& par : ucesnici) {
cout << par.first << ": " << par.second << endl;
}
Prednosti:
- Jednostavan i lak za razumevanje.
- Efikasnost: Koristi const auto& da izbegne kopiranje parova.
- Pogodan za slučajeve kada nije potrebna direktna kontrola nad elementima mape.
- Manjak fleksibilnosti kada je potrebna modifikacija elemenata ili specifično pozicioniranje.
2. Iteratori
Iteratori omogućavaju veću fleksibilnost jer pružaju direktan pristup elementima, što može biti korisno kada je potrebno menjati sadržaj mape ili kontrolisati tok iteracije.
Primer:
Primer:
map<string, int> ucesnici = {{"Marko", 3}, {"Ana", 2}, {"Ivan", 1}};
for (auto it = ucesnici.begin(); it != ucesnici.end(); ++it) {
cout << it->first << ": " << it->second << endl;
}
for (auto it = ucesnici.begin(); it != ucesnici.end(); ++it) {
cout << it->first << ": " << it->second << endl;
}
Prednosti:
- Omogućava promenu vrednosti elemenata tokom iteracije.
- Omogućava pristup složenim operacijama, poput brisanja trenutnog elementa (it = mapa.erase(it)).
- Kod može postati manje čitljiv, posebno za početnike.
- Složeniji pristup u poređenju sa opsežnom petljom.
- Za iteraciju kroz sve elemente mape, oba pristupa su podjednako efikasna jer imaju vremensku složenost O(n).
- Opsežna for petlja je često pogodnija kada radite samo sa očitavanjem elemenata, dok iteratori pružaju više fleksibilnosti za modifikacije.
Preporuke za upotrebu
- Koristite opsežnu petlju (for) kada vam je potrebna jednostavna iteracija kroz sve elemente bez izmene sadržaja.
- Koristite iteratore kada je potrebno menjati vrednosti elemenata, preskakati određene elemente ili brisati elemente iz mape tokom iteracije.
Učitavanje mape c++
Drugi način da se mapa popuni vrednostima je učitavanje sa standardnog ulaza, kada se od korisnika zatraži da unese ime učenika, kao i njegov ostvaren uspeh.
Unošenje para kluč vrednost, može se dodati u mapu na njen kraj sa funkcijom insert. Posmatrajmo sledeći kod:
Unošenje para kluč vrednost, može se dodati u mapu na njen kraj sa funkcijom insert. Posmatrajmo sledeći kod:
//Ucitavanje para kljuc vrednost u mapu;
int n;
string ime;
double prosek;
cout << " Unesi broj ucenika" << endl;
cin >> n;
for(int i = 0; i < n; i++){
//ispisivanje podataka smeštenih unutar mape
for(auto parKljucVrednost: prosek){
int n;
string ime;
double prosek;
cout << " Unesi broj ucenika" << endl;
cin >> n;
for(int i = 0; i < n; i++){
cout << "Unesi ime ucenika " << endl;
cin >> ime;
cout << "unesi prosek " << endl;
cin >> prosek;
prosekMap.insert(pair <string, double> (ime,prosek));
}cin >> ime;
cout << "unesi prosek " << endl;
cin >> prosek;
prosekMap.insert(pair <string, double> (ime,prosek));
//ispisivanje podataka smeštenih unutar mape
for(auto parKljucVrednost: prosek){
cout << parKljucVrednost.first << " " << parKljucVrednost.second << endl;
}Unos podataka u mapu sa proverom da li vrednost ključa već postoji u mapi
Unos podataka u mapu sa operatorom []
Primer:
Pretpostavimo da imamo definisanu mapu u c++, gde ključevi predstavljaju npr. učesnike na takmičenju(imena), a vrednosti broj odigranih mečeva. Želimo da pri unosu učesnika u for petlji ispitamo da li je tekuci učesnik vec unutar mape(ključ), pa ako jeste da povećamo broj učešća za 1.
Potrebno je i postaviti početnu vrednosnt učešća na 0 i da li je to potrebno. Mapa:
map<string,int>ucesnici;
Pretpostavimo da imamo definisanu mapu u c++, gde ključevi predstavljaju npr. učesnike na takmičenju(imena), a vrednosti broj odigranih mečeva. Želimo da pri unosu učesnika u for petlji ispitamo da li je tekuci učesnik vec unutar mape(ključ), pa ako jeste da povećamo broj učešća za 1.
Potrebno je i postaviti početnu vrednosnt učešća na 0 i da li je to potrebno. Mapa:
map<string,int>ucesnici;
Rešenje:
Operator [] automatski dodaje ključ na mapu ako ne postoji i postavlja vrednost na podrazumevanu vrednost za tip (0 za int u ovom slučaju).
Operator [] automatski dodaje ključ na mapu ako ne postoji i postavlja vrednost na podrazumevanu vrednost za tip (0 za int u ovom slučaju).
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, int> ucesnici;
// Primer unosa učesnika
string unosi[] = {"Marko", "Ana", "Marko", "Ivan", "Ana"};
for (const string& ime : unosi) {
ucesnici[ime]++; // Povećava broj učešća (podrazumevana vrednost za nove ključeve je 0)
}
// Ispis mape
for (const auto& par : ucesnici) {
cout << "Ucesnik: " << par.first << ", Broj ucesca: " << par.second << endl;
}
return 0;
}
#include <map>
#include <string>
using namespace std;
int main() {
map<string, int> ucesnici;
// Primer unosa učesnika
string unosi[] = {"Marko", "Ana", "Marko", "Ivan", "Ana"};
for (const string& ime : unosi) {
ucesnici[ime]++; // Povećava broj učešća (podrazumevana vrednost za nove ključeve je 0)
}
// Ispis mape
for (const auto& par : ucesnici) {
cout << "Ucesnik: " << par.first << ", Broj ucesca: " << par.second << endl;
}
return 0;
}
Objašnjenje:
- Operator []: Ako ključ (npr. "Marko") ne postoji u mapi, kreira ga sa podrazumevanom vrednošću (0 za int). Zatim se vrednost povećava za 1.
- Početna vrednost: Nije potrebno ručno postaviti početnu vrednost na 0 jer to radi operator [].
Napomena:
Ako koristimo:
Ako koristimo:
ucesnici["NoviUcesnik"]++;
To dodaje "NoviUcesnik" sa vrednošću 1, čak i ako nije bio prethodno unet.
Da bismo ovo izbegli, koristimo find:
Da bismo ovo izbegli, koristimo find:
auto it = ucesnici.find("NoviUcesnik");
if (it != ucesnici.end()) {
it->second++;
} else {
cout << "Učesnik nije pronađen!" << endl;
}
if (it != ucesnici.end()) {
it->second++;
} else {
cout << "Učesnik nije pronađen!" << endl;
}
Alternativa sa find:
Ako želite da izbegnete automatsko kreiranje ključa, koristite find:
if (ucesnici.find(ime) != ucesnici.end()) {
ucesnici[ime]++;
} else {
ucesnici[ime] = 1;
}
ucesnici[ime]++;
} else {
ucesnici[ime] = 1;
}
Prepisivanje iz jedne mape u drugu c++
Deklariše se mapa prosekMap2 koja će imati iste elemente kao i mapa 1. Prilikom deklarisanja treba proslediti pokazivače na početak i kraj prve mape.
//prepisivanje mape
cout << "Mapa 2: "<< endl;
map < string, double>prosekMap2(prosekMap.begin(),prosekMap.end());
ispisi(prosekMap2);
cout << "Mapa 2: "<< endl;
map < string, double>prosekMap2(prosekMap.begin(),prosekMap.end());
ispisi(prosekMap2);
Ovde smo ispisivanje vrednosti mape premestili u posebnu funkciju ispisi, kojoj se za parametar prosleđuje pokazivač na mapu koju treba ispisati.
void ispisi(map < string, double> prosekMap){
//ispisivanje podataka smeštenih unutar mape
for(auto parKljucVrednost: prosekMap){
}for(auto parKljucVrednost: prosekMap){
cout << parKljucVrednost.first << " " << parKljucVrednost.second << endl;
}Posle pokretanja:
Ispisivanje mape pomoću iteratora
Definišemo iterator (kursor) koji pokazuje na određen par unutar mape i može lako da se premešta kroz mapu:
map<string, double>::iterator itr;
Ispisivanje kroz petlju bi bilo:
map<string, double>::iterator itr;
Ispisivanje kroz petlju bi bilo:
void ispisi2(map < string, double> prosekMap){
//ispisivanje podataka smeštenih unutar mape
map < string, double >::iterator itr;
for(itr = prosekMap.begin(); itr !=prosekMap.end(); ++itr ){
}map < string, double >::iterator itr;
for(itr = prosekMap.begin(); itr !=prosekMap.end(); ++itr ){
cout << itr -> first << " " << itr -> second << endl;
}Brisanje elemenata u mapi c++
Brisanje elemenata iz mape se može ostvariti funkcijom erase
Brisanje elemenata sa odrećenom vrednošću ključa
Ako želimo da obrišemo element čiji je ključ npr vrednost imeZaBrisanje, to se može uraditi na sledeći način:
//Brisanje elemenata sa odrećenom vrednošću ključa
string imeZaBrisanje = "Nikola";
prosekMap2.erase(imeZaBrisanje);
cout << "Posle brisanja, mapa 2 izgleda " << endl;
ispisi2(prosekMap2);
string imeZaBrisanje = "Nikola";
prosekMap2.erase(imeZaBrisanje);
cout << "Posle brisanja, mapa 2 izgleda " << endl;
ispisi2(prosekMap2);
Brisanje svih elemenata u mapi
//Brisanje elemenata sa odrećenom vrednošću ključa
prosekMap2.clear();
cout << "Posle brisanja, komandom clear broj elemenata u mapi 2 je " << prosekMap2.size();
prosekMap2.clear();
cout << "Posle brisanja, komandom clear broj elemenata u mapi 2 je " << prosekMap2.size();
Posle brisanja mapa 2 neće imati ni jedan element, tj. veličina mape je nula.
Brisanje elemenata u mapama: Preporuke i oprez
Funkcija erase omogućava brisanje elemenata iz mape pomoću ključa, iteratora, ili opsega iteratora. Međutim, prilikom korišćenja ove funkcije treba obratiti pažnju na nekoliko potencijalnih grešaka:
- Brisanje nepostojećeg ključa
Ako pokušate da obrišete ključ koji ne postoji u mapi, erase neće izazvati grešku, ali neće imati efekta. Kako biste izbegli nepotrebne operacije, preporučuje se prethodna provera prisustva ključa:
auto it = mapa.find(kljuc);
if (it != mapa.end()) {
mapa.erase(it);
}
if (it != mapa.end()) {
mapa.erase(it);
}
2. Brisanje tokom iteracije
Kada brišete elemente dok iterirate kroz mapu, upotrebite povratnu vrednost erase (novi iterator koji pokazuje na sledeći element) kako biste izbegli invalidaciju iteratora:
Kada brišete elemente dok iterirate kroz mapu, upotrebite povratnu vrednost erase (novi iterator koji pokazuje na sledeći element) kako biste izbegli invalidaciju iteratora:
for (auto it = mapa.begin(); it != mapa.end(); ) {
if (uslov) {
it = mapa.erase(it);
} else {
++it;
}
}
if (uslov) {
it = mapa.erase(it);
} else {
++it;
}
}
3. Brisanje više elemenata (opsežno brisanje)
Kada želite da obrišete sve elemente u datom opsegu, koristite erase sa opsegom iteratora:
Kada želite da obrišete sve elemente u datom opsegu, koristite erase sa opsegom iteratora:
mapa.erase(mapa.begin(), mapa.find("kljucevi_do_ovde"));
Ovo može biti korisno za efikasno brisanje većeg broja elemenata.
4. Uticaj na performanse
Funkcija erase ima složenost O(logN) za pojedinačne elemente, dok brisanje celog opsega može biti brže jer se operacije optimizuju za veće skupove podataka. Preporučuje se da birate pristup u zavisnosti od broja elemenata za brisanje.
5. Praktični saveti
6. Primer greške
Ukoliko koristite iterator koji je postao nevalidan nakon brisanja:
4. Uticaj na performanse
Funkcija erase ima složenost O(logN) za pojedinačne elemente, dok brisanje celog opsega može biti brže jer se operacije optimizuju za veće skupove podataka. Preporučuje se da birate pristup u zavisnosti od broja elemenata za brisanje.
5. Praktični saveti
- Kada koristiti find pre erase: Kod kritičnih sistema ili gde postoji neizvesnost o prisustvu ključa.
- Kada koristiti direktno erase: Kada ste sigurni da ključ postoji ili u jednostavnim slučajevima.
6. Primer greške
Ukoliko koristite iterator koji je postao nevalidan nakon brisanja:
auto it = mapa.erase(mapa.begin());
cout << it->first; // Ispravno, iterator je validan.
cout << it->first; // Ispravno, iterator je validan.
Pronalaženje vrednosti po kljucu c++
Ukoliko se zna ključ, prvo se pomocu find funkcije vrati iterator koji pokazuje na onaj par ciji je ključ prosledjen funkciji. Zatim se pomoću iteratora može izvući vrednost, kao što je pokazano u sledećem kodu:
//pretraga mape
string kljuc="Mika";
map<string, double>::iterator it;
it=prosekMap.find(kljuc);
cout << endl << it -> first << " ima prosek " << it->second;
string kljuc="Mika";
map<string, double>::iterator it;
it=prosekMap.find(kljuc);
cout << endl << it -> first << " ima prosek " << it->second;
Sortiranje mape po vrednosti
Prvo treba prebaciti elemente u vector:
// Deklarisanje vektora parova iz mape
vector < pair < string, double > > A;
// Copy key-value pair from Map
// to vector of pairs
for (auto& it : prosekMap) {
vector < pair < string, double > > A;
// Copy key-value pair from Map
// to vector of pairs
for (auto& it : prosekMap) {
A.push_back(it);
}Zatim se vrši sortiranje funkcijom sort
sort(A.begin(),A.end());
cout << " Posle sortiranja mapa izgleda: " << endl;
cout << "Sortiran vektor:" << endl;
for(auto & it:A)
{
cout << " Posle sortiranja mapa izgleda: " << endl;
cout << "Sortiran vektor:" << endl;
for(auto & it:A)
{
cout << it.first << ": " << it.second << endl;
}Posle pokretanja:
Prolazak kroz vektor sa parovima ključ-vrednost kao elementima (pair<string,int>) bi mogao da bude i na sledeći način:
sort(A.begin(),A.end());
cout << " Posle sortiranja mapa izgleda: " << endl;
cout << "Sortiran vektor:" << endl;
for(pair<string,int> par:A) {
cout << " Posle sortiranja mapa izgleda: " << endl;
cout << "Sortiran vektor:" << endl;
for(pair<string,int> par:A) {
cout << par.first << " "<< par.second << endl;
}Sortiranje mape po vrednosti u opadajućem poretku
Primer: Zapisani su rezultate 4 četvrtfinalna meča, 2 polufinalna meča i finalnog meča nokaut faze turnira (ukupno
7 mečeva). Rezultati koji su dati na ulazu nisu sortirani (na primer, poslednji red na ulazu ne znači nužno da je taj meč poslednji odigran). Odrediti pobednika i drugoplasiranog na turniru.
Pretpostavimo da su u mapu već uneti sortirani podaci.
7 mečeva). Rezultati koji su dati na ulazu nisu sortirani (na primer, poslednji red na ulazu ne znači nužno da je taj meč poslednji odigran). Odrediti pobednika i drugoplasiranog na turniru.
Pretpostavimo da su u mapu već uneti sortirani podaci.
U C++, pošto std::map ne podržava direktno sortiranje po vrednosti (jer se ona sortira po ključu), možete prebaciti parove iz mape u vektor, sortirati vektor po vrednosti, i zatim ispisati prva dva učesnika s najvećim brojem učešća. Evo primera kako to može da se uradi:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
map<string, int> ucesnici = {
{"Petar", 5},
{"Ana", 8},
{"Marko", 3},
{"Jovana", 7}
};
// Prebacivanje parova u vektor
vector<pair<string, int>> ucesniciVektor(ucesnici.begin(), ucesnici.end());
// Sortiranje vektora po vrednosti, opadajuće
sort(ucesniciVektor.begin(), ucesniciVektor.end(),
[](const pair<string, int>& a, const pair<string, int>& b) {
return a.second > b.second; // Sortira opadajuće po broju učešća
});
// Ispis prvih dva učesnika sa najvećim brojem učešća
cout << "Prva dva učesnika sa najvećim brojem učešća su:\n";
for (int i = 0; i < min(2, (int)ucesniciVektor.size()); ++i) {
cout << ucesniciVektor[i].first << " (" << ucesniciVektor[i].second << " učešća)\n";
}
return 0;
}
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
map<string, int> ucesnici = {
{"Petar", 5},
{"Ana", 8},
{"Marko", 3},
{"Jovana", 7}
};
// Prebacivanje parova u vektor
vector<pair<string, int>> ucesniciVektor(ucesnici.begin(), ucesnici.end());
// Sortiranje vektora po vrednosti, opadajuće
sort(ucesniciVektor.begin(), ucesniciVektor.end(),
[](const pair<string, int>& a, const pair<string, int>& b) {
return a.second > b.second; // Sortira opadajuće po broju učešća
});
// Ispis prvih dva učesnika sa najvećim brojem učešća
cout << "Prva dva učesnika sa najvećim brojem učešća su:\n";
for (int i = 0; i < min(2, (int)ucesniciVektor.size()); ++i) {
cout << ucesniciVektor[i].first << " (" << ucesniciVektor[i].second << " učešća)\n";
}
return 0;
}
PRIMER SA UPOTREBOM MAPA: Pogledajte primer broj 11 sa webstrane: Kvalifikacije za okružna takmičenja
Sortiranje mape prema vrednostima-nastavak
Standardna std::map u C++ uvek održava redosled elemenata prema ključu. Ovo je korisno kada je sortiranje prema ključevima poželjno, ali ako želite da mapu sortirate prema vrednostima, neophodno je koristiti alternativne pristupe jer std::map ne podržava direktno sortiranje prema vrednostima.
Sortiranje prebacivanjem u vektor parovaJedan od najčešće korišćenih pristupa je prebacivanje elemenata mape u vektor parova i zatim korišćenje std::sort sa prilagođenim komparatorom:
Sortiranje prebacivanjem u vektor parovaJedan od najčešće korišćenih pristupa je prebacivanje elemenata mape u vektor parova i zatim korišćenje std::sort sa prilagođenim komparatorom:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
map<string, int> ucesnici = {{"Ana", 5}, {"Marko", 3}, {"Ivan", 8}};
// Prebacivanje u vektor
vector<pair<string, int>> vektor(ucesnici.begin(), ucesnici.end());
// Sortiranje prema vrednostima
sort(vektor.begin(), vektor.end(),
[](const pair<string, int>& a, const pair<string, int>& b) {
return a.second > b.second; // Opadajući redosled
});
// Ispis sortiranih elemenata
for (const auto& par : vektor) {
cout << par.first << ": " << par.second << endl;
}
return 0;
}
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
map<string, int> ucesnici = {{"Ana", 5}, {"Marko", 3}, {"Ivan", 8}};
// Prebacivanje u vektor
vector<pair<string, int>> vektor(ucesnici.begin(), ucesnici.end());
// Sortiranje prema vrednostima
sort(vektor.begin(), vektor.end(),
[](const pair<string, int>& a, const pair<string, int>& b) {
return a.second > b.second; // Opadajući redosled
});
// Ispis sortiranih elemenata
for (const auto& par : vektor) {
cout << par.first << ": " << par.second << endl;
}
return 0;
}
Korisni saveti
- Performanse: Ovaj pristup je efikasan za manje skupove podataka, ali za veće mape može biti sporiji jer se celokupan sadržaj kopira u vektor.
- Stabilnost: Funkcija std::sort nije stabilna, što znači da elementi sa istim vrednostima neće nužno zadržati originalni redosled.
#include <iostream>
#include <map>
using namespace std;
int main() {
multimap<int, string> obrnuto;
// Pretvaranje iz mape
map<string, int> ucesnici = {{"Ana", 5}, {"Marko", 3}, {"Ivan", 8}};
for (const auto& par : ucesnici) {
obrnuto.insert({par.second, par.first});
}
// Ispis sortiranih elemenata
for (const auto& par : obrnuto) {
cout << par.second << ": " << par.first << endl;
}
return 0;
}
#include <map>
using namespace std;
int main() {
multimap<int, string> obrnuto;
// Pretvaranje iz mape
map<string, int> ucesnici = {{"Ana", 5}, {"Marko", 3}, {"Ivan", 8}};
for (const auto& par : ucesnici) {
obrnuto.insert({par.second, par.first});
}
// Ispis sortiranih elemenata
for (const auto& par : obrnuto) {
cout << par.second << ": " << par.first << endl;
}
return 0;
}
Napomena o prilagođenim komparatorima
Ako želite da direktno koristite std::map sa sortiranim vrednostima, možete koristiti prilagođeni komparator, ali to zahteva dodatno praćenje parova ključeva i vrednosti, što često nije praktično.
Preporuka
Ako želite da direktno koristite std::map sa sortiranim vrednostima, možete koristiti prilagođeni komparator, ali to zahteva dodatno praćenje parova ključeva i vrednosti, što često nije praktično.
Preporuka
- Za dinamične strukture: Koristite vektore ili std::multimap.
- Za fiksne strukture: Prebacivanje u vektor i sortiranje je jednostavniji pristup.
Neuređene mape(unordered engl. map)
Neuređene mape se koriste kada nije potrebno voditi računa o redosledu ključeva, a sa druge strane, veća je brzina pristupa pojedinim ključevima u nesortiranoj mapi.
Da bi koristili neodređene mape potrebno je uključiti sledeće zaglavlje:
Pogledajmo razlike između uređene i neuređene mape, tj. njihove prednosti i mane:
Da bi koristili neodređene mape potrebno je uključiti sledeće zaglavlje:
Pogledajmo razlike između uređene i neuređene mape, tj. njihove prednosti i mane:
#include < unordered_map >
map protiv unordered_map
Osobine za map:
- Implementacija: map je implementiran kao uravnoteženo binarno stablo pretraživanja (najčešće crveno-crno stablo).
- Sortiranje: Ključevi u map su uvijek sortirani u rastućem poretku.
- Kompleksnost: Operacije umetanja, brisanja i pristupa elementima imaju složenost O(log n) zbog strukture stabla.
- Redosled iteracije: Iteracija kroz map će uvek biti u sortiranom redosledu ključeva.
Kada se koristi:
- Kada je potrebno sortirano skladištenje parova ključ-vrednost.
- Kada je potrebna logaritamska vremenska složenost operacija.
- Kada je bitan redosled iteracije.
Osobine za unordered_map:
- Implementacija: unordered_map je implementiran kao heš tabela.
- Sortiranje: Ključevi u unordered_map nisu sortirani; elementi su raspoređeni na osnovu rezultata heš funkcije.
- Kompleksnost: Operacije umetanja, brisanja i pristupa elementima imaju prosečnu složenost O(1), ali u najgorem slučaju složenost može biti O(n) zbog mogućih sudara heš vrednosti.
- Redosled iteracije: Iteracija kroz unordered_map ne prati nikakav redosled ključeva.
Kada se koristi?
- Kada je potrebno brže skladištenje i pristup elementima (u proseku).
- Kada nije bitan redosled ključeva.
- Kada se radi sa velikim skupovima podataka i kada su sudari heš vrednosti minimalni ili dobro kontrolisani.
Primer za uređenu mapu
Tekst: Zadati 3 para za mapu, a zatim ispisati parove kluč vrednost.
Rešenje:
Rešenje:
#include < iostream >
#include < map >
using namespace std;
int main() {
#include < map >
using namespace std;
int main() {
map mojaMapa;
mojaMapa[1] = "jedan";
mojaMapa[3] = "tri";
mojaMapa[2] = "dva";
for (const auto& par: mojaMapa) {
return 0;
}mojaMapa[1] = "jedan";
mojaMapa[3] = "tri";
mojaMapa[2] = "dva";
for (const auto& par: mojaMapa) {
cout << par.first << ": " << par.second << endl;
}return 0;
Izlaz:
1: jedan
2: dva
3: tri
2: dva
3: tri
Primer za neuređenu mapu
Tekst: Zadati 3 para za neuređenu mapu, a zatim ispisati parove kluč vrednost.
Rešenje:
Rešenje:
#include < iostream >
#include < unordered_map >
using namespace std;
int main() {
#include < unordered_map >
using namespace std;
int main() {
unordered_map< int, string > mojaNeuređenaMapa;
mojaNeuređenaMapa[1] = "jedan";
mojaNeuređenaMapa[3] = "tri";
mojaNeuređenaMapa[2] = "dva";
for (const auto& par: mojaNeuređenaMapa) {
return 0;
}mojaNeuređenaMapa[1] = "jedan";
mojaNeuređenaMapa[3] = "tri";
mojaNeuređenaMapa[2] = "dva";
for (const auto& par: mojaNeuređenaMapa) {
cout << par.first << ": " << par.second << endl;
}return 0;
Primeri korišćenja u praksi
Mape u C++ su korisne za rešavanje širokog spektra realnih problema gde je potrebno uspostaviti vezu između ključa i vrednosti.
1. Brojanje frekvencija reči u tekstu
Jedan od klasičnih primera primene mape je brojanje koliko se puta svaka reč pojavljuje u tekstu:
#include <iostream>
#include <map>
#include <string>
#include <sstream>
using namespace std;
int main() {
string tekst = "ovo je primer teksta u kojem brojimo reci reci su kljucne";
map<string, int> frekvencije;
// Podela teksta na reči
stringstream ss(tekst);
string rec;
while (ss >> rec) {
frekvencije[rec]++;
}
// Ispis rezultata
for (const auto& par : frekvencije) {
cout << "Reč: " << par.first << ", Pojavljivanja: " << par.second << endl;
}
return 0;
}
#include <map>
#include <string>
#include <sstream>
using namespace std;
int main() {
string tekst = "ovo je primer teksta u kojem brojimo reci reci su kljucne";
map<string, int> frekvencije;
// Podela teksta na reči
stringstream ss(tekst);
string rec;
while (ss >> rec) {
frekvencije[rec]++;
}
// Ispis rezultata
for (const auto& par : frekvencije) {
cout << "Reč: " << par.first << ", Pojavljivanja: " << par.second << endl;
}
return 0;
}
Praktična primena: Ovaj primer može biti osnova za implementaciju jednostavnog analizatora teksta, npr. za prebrojavanje ključnih reči u dokumentima.
2. Praćenje ocena studenata
Mapa se može koristiti za praćenje proseka ocena studenata:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, double> studenti;
studenti["Marko"] = 8.5;
studenti["Ana"] = 9.2;
studenti["Ivan"] = 7.8;
// Ispis proseka ocena
for (const auto& par : studenti) {
cout << "Student: " << par.first << ", Prosek: " << par.second << endl;
}
return 0;
}
#include <map>
#include <string>
using namespace std;
int main() {
map<string, double> studenti;
studenti["Marko"] = 8.5;
studenti["Ana"] = 9.2;
studenti["Ivan"] = 7.8;
// Ispis proseka ocena
for (const auto& par : studenti) {
cout << "Student: " << par.first << ", Prosek: " << par.second << endl;
}
return 0;
}
Praktična primena: Ovaj pristup može se koristiti u sistemima za upravljanje školama ili univerzitetima.
3. Implementacija telefonskog imenika
Mapa omogućava jednostavno kreiranje telefonskog imenika gde se imena mapiraju na brojeve telefona:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, string> imenik;
imenik["Marko"] = "0641234567";
imenik["Ana"] = "0659876543";
// Pretraga u imeniku
string trazenoIme = "Ana";
if (imenik.find(trazenoIme) != imenik.end()) {
cout << "Broj telefona za " << trazenoIme << ": " << imenik[trazenoIme] << endl;
} else {
cout << "Kontakt nije pronađen." << endl;
}
return 0;
}
#include <map>
#include <string>
using namespace std;
int main() {
map<string, string> imenik;
imenik["Marko"] = "0641234567";
imenik["Ana"] = "0659876543";
// Pretraga u imeniku
string trazenoIme = "Ana";
if (imenik.find(trazenoIme) != imenik.end()) {
cout << "Broj telefona za " << trazenoIme << ": " << imenik[trazenoIme] << endl;
} else {
cout << "Kontakt nije pronađen." << endl;
}
return 0;
}
Praktična primena: Ovakva struktura može se koristiti u aplikacijama za upravljanje kontaktima.
Predlozi za dodatna proširenja
Predlozi za dodatna proširenja
- Dodati primere za složenije aplikacije, poput implementacije rang lista, sistema za glasanje ili upravljanje inventarom.
- Uključiti vizuelne prikaze podataka pomoću biblioteka za grafiku ili izveštaje (npr. sortirane rang-liste ili grafikone).
Dodaci: Napredne funkcije i poređenje sa unordered_map
Funkcija emplace
Funkcija emplace omogućava umetanje elemenata u mapu direktno na njihovoj lokaciji u memoriji, čime se često smanjuju troškovi kopiranja u poređenju sa insert. To može dovesti do boljih performansi, posebno kod umetanja složenijih tipova podataka. Na primer:
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, int> ucesnici;
// Umetanje pomoću emplace
ucesnici.emplace("Marko", 5);
ucesnici.emplace("Ana", 3);
for (const auto& par : ucesnici) {
cout << "Ucesnik: " << par.first << ", Broj ucesca: " << par.second << endl;
}
return 0;
}
#include <map>
using namespace std;
int main() {
map<string, int> ucesnici;
// Umetanje pomoću emplace
ucesnici.emplace("Marko", 5);
ucesnici.emplace("Ana", 3);
for (const auto& par : ucesnici) {
cout << "Ucesnik: " << par.first << ", Broj ucesca: " << par.second << endl;
}
return 0;
}
Razlika u odnosu na insert:
Dok insert prima već kreirani par (ili kopiju), emplace konstruiše objekat direktno na odgovarajućoj lokaciji, čime se izbegavaju dodatne operacije kopiranja ili premještanja.
Poređenje std::map i std::unordered_mapstd::map:
Dok insert prima već kreirani par (ili kopiju), emplace konstruiše objekat direktno na odgovarajućoj lokaciji, čime se izbegavaju dodatne operacije kopiranja ili premještanja.
Poređenje std::map i std::unordered_mapstd::map:
- Implementacija zasnovana na uravnoteženom binarnom stablu (npr. Red-Black Tree).
- Održava elemente sortiranim po ključu.
- Operacije umetanja, pretrage i brisanja imaju logaritamsku složenost O(logn).
- Pogodno kada je redosled elemenata važan.
std::unordered_map:
- Implementacija zasnovana na hash tabeli.
- Elementi nisu sortirani.
- Operacije umetanja, pretrage i brisanja imaju amortizovanu konstantnu složenost O(1), ali mogu biti O(n) u najgorem slučaju.
- Pogodno kada je performansa pretrage prioritet, a redosled nije bitan.
Primer poređenja:
#include <iostream>
#include <map>
#include <unordered_map>
using namespace std;
int main() {
map<string, int> sortiranaMapa;
unordered_map<string, int> hashMapa;
sortiranaMapa["Marko"] = 5;
sortiranaMapa["Ana"] = 3;
hashMapa["Marko"] = 5;
hashMapa["Ana"] = 3;
// Ispis
cout << "Sortirana mapa (std::map):" << endl;
for (const auto& par : sortiranaMapa) {
cout << par.first << ": " << par.second << endl;
}
cout << "\nHash mapa (std::unordered_map):" << endl;
for (const auto& par : hashMapa) {
cout << par.first << ": " << par.second << endl;
}
return 0;
}
#include <map>
#include <unordered_map>
using namespace std;
int main() {
map<string, int> sortiranaMapa;
unordered_map<string, int> hashMapa;
sortiranaMapa["Marko"] = 5;
sortiranaMapa["Ana"] = 3;
hashMapa["Marko"] = 5;
hashMapa["Ana"] = 3;
// Ispis
cout << "Sortirana mapa (std::map):" << endl;
for (const auto& par : sortiranaMapa) {
cout << par.first << ": " << par.second << endl;
}
cout << "\nHash mapa (std::unordered_map):" << endl;
for (const auto& par : hashMapa) {
cout << par.first << ": " << par.second << endl;
}
return 0;
}
Kada koristiti koju?
- std::map: Kada je redosled bitan ili kada treba iterirati kroz elemente u sortiranom poretku.
- std::unordered_map: Kada je potrebna brza pretraga, a redosled nije važan.
Prethodno
|< Dinamički niz-vector |
Sledeće
Dvodimenzionalni nizovi - matrice >| |