====== std::unordered_map και std::unordered_multimap ======
Ένα [[http://www.cplusplus.com/reference/unordered_map/unordered_map/|std::unordered_map]] αποτελεί ένα σύνολο μοναδικών στοιχείων, όπου κάθε τέτοιο στοιχείο αποτελεί κλειδί για την εύρεση ή αντιστοίχιση του με ένα άλλο αντικείμενο που ονομάζουμε "τιμή" (//value//). Κάθε κλειδί προσδιορίζει μοναδικά μία "τιμή", η οποία δεν είναι απαραίτητο να είναι μοναδική (οι τιμές μπορεί να επαναλαμβάνονται).
Τα κλειδιά του [[http://www.cplusplus.com/reference/unordered_map/unordered_map/|std::unordered_map]] είναι αποθηκευμένα σε ένα πίνακα κατακερματισμού με αλύσίδες ([[wp>Hash_table#Separate_chaining]]).
Η κατάταξη ενός νέου ζεύγους κλειδιού-τιμής γίνεται πάντα μέσω της συνάρτησης κατακερματισμού (//hash function//), η οποία εξαρτάται από το είδος των κλειδιών που αποθηκεύονται στο //map//. Το ακόλουθο σχήμα περιγράφει συνοπτικά τη δομή της κλάσης //unordered_map//.
| {{ :cpp:stl:internal_structure_of_unordered_maps_and_multimaps.png?600 |}} |
| Σχήμα 1. Η δομή της κλάσης [[http://www.cplusplus.com/reference/unordered_map/unordered_map/|std::unordered_map]] (Πηγή: [[https://conglang.github.io/2015/01/01/stl-unordered-container/|conglang.github.io]])|
===== Επίδοσης της δομής =====
Η επίδοση της δομής είναι ανάλογη των δομών [[cpp:stl:unordered_set|std::unordered_set και std::unordered_multiset]] λαμβάνοντας υπόψη τα στοιχεία-κλειδιά των //std::unordered_map// και //std::unordered_multimap//.
===== Περισσότερα για τις κλάσεις std::unordered_map και std::unordered_multimap =====
H δήλωση της κλάσης //std::unordered_map// έχει ως εξής:
template < class Key, // unordered_map::key_type
class T, // unordered_map::mapped_type
class Hash = hash, // unordered_map::hasher
class Pred = equal_to, // unordered_map::key_equal
class Alloc = allocator< pair > // unordered_map::allocator_type
> class unordered_map;
Από την παραπάνω δήλωση της κλάσης παρατηρούμε ότι εκτός από το κλειδί ''Key'' και τον τύπο ''T'' που αντιστοιχεί στην τιμή κάθε ζεύγους κλειδιού-τιμής, κατά την δήλωση της κλάσης απαιτείται η δήλωση δύο επιπλέον κλάσεων //α)// της κλάσης ''Hash=hash'' και //β)// της κλάσης ''Pred=equal_to''. Οι κλάσεις αυτές λειτουργούν ως συναρτήσεις (δες σχετικό παράδειγμα στη συνέχεια). Η πρώτη υλοποιεί το //hash function// για την τοποθέτηση σε μία θέση του //hash table// (μία θέση ονομάζεται και //bucket//) και η δεύτερη ελέγχει την ισότητα μεταξύ δύο αντικειμένων του ιδίου τύπου για την αναζήτηση μέσα στη λίστα του κάθε //bucket//.
Για τους βασικούς τύπους δεδομένων οι παραπάνω κλάσεις υλοποιούνται μέσω των //templated// κλάσεων [[http://www.cplusplus.com/reference/functional/hash/|std::hash]] και [[http://www.cplusplus.com/reference/functional/equal_to/|std::equal_to]]. Για δικούς σας τύπους δεδομένων καλείστε να υλοποιήσετε εσείς τις συγκεκριμένες συναρτήσεις.
===== Παράδειγμα 1ο - Αποθήκευση std::string ως κλειδί σε unordered_map ή unordered_multimap =====
#include
Αλλάξτε τον //STL container// από //std::unordered_map// σε //std::unordered_multimap// και παρατηρήστε την συμπεριφορά του προγράμματος σε αυτή την περίπτωση.
===== Παράδειγμα 2ο - Αποθήκευση Student ως κλειδί σε unordered_map ή unordered_multimap =====
#include
#include
#include "Student.hpp"
template
void print(std::unordered_map s) {
for(auto it = s.cbegin(); it!=s.cend(); it++)
std::cout << it->first << " -> " << it->second << std::endl;
}
struct HashByAEM {
size_t operator()(const Student& st) const {
std::hash hash_int;
return hash_int(st.getAEM());
}
};
struct EqualToByAEM {
bool operator() (const Student& st1, const Student& st2) const {
return st1.getAEM() == st2.getAEM();
}
};
int main(int argc, char *argv[]) {
// map students to their address
std::unordered_map students;
std::pair peter_pan_pair(Student("Peter Pan", 1234), std::string("Wendy House, Neverland"));
std::pair mickey_mouse_pair = make_pair(Student("Mickey Mouse", 1235), std::string("Walt Disney World Communications, P.O Box 10040, Lake Buena Vista, Florida 32830-0040 "));
students.insert( peter_pan_pair );
students.insert( mickey_mouse_pair );
students.emplace( Student("Minie Mouse", 1240), std::string("Walt Disney World Communications, P.O Box 10040, Lake Buena Vista, Florida 32830-0040 "));
print(students);
return 0;
}
Αλλάξτε τον //STL container// από //std::unordered_set// σε //std::unordered_multiset// και παρατηρήστε τη συμπεριφορά του προγράμματος και σε αυτή την περίπτωση.