Associative Containers Sets and Maps • Section 4.8 Generic Associative Containers • A generic container C – C is a template class for any proper type T – C<T> is capable of storing arbitrary number of T objects • A container that is organized and accessible by value – – – – Client may insert or remove any T object in C<T> Client may not determine position in C<T> Positional details left to implementation The order of elements in container is independent of the order in which they are inserted into container • “aContainer” for short • Bidirectional Iterators – Both ++ and -- operations are supported Multimodal vs. Unimodal Associative Containers • Multimodal associative container – Duplicate elements are allowed – Insert operations always increase size by 1 • Unimodal associative container – Duplicate elements not allowed – Insert operations have dual personality • If t is not in C, then Insert(t) • If t is in C, then overwrite the existing t The Pair Template • A class that holds a pair of items (may be of different types) template <typename T1, typename T2> class Pair { public: T1 first; T2 second; Pair() {}; Pair(const T1& t1, const T2& t2): first(t1), second(t2) {}; }; • Examples Pair<int, int> pair1; Pair<string, int> pair2; • C++/STL #include <utility> pair<int, int> pair1 pair<string, int> pair2 Sets & Maps Sets • Sorted associative containers • Set – A sorted associative container that does not allow duplicates – Stores objects – Unimodal: duplicate objects not allowed The STL Set Template • • set() // Creates an empty set. set(const key_compare& comp) //Creates an empty set, use comp for key comparison • • pair<iterator, bool> insert(const value_type& x) iterator insert(iterator pos, const value_type& x) – Inserts x into the set, using pos as a hint to where it will be inserted. • void erase(iterator pos) – Erases the element pointed to by pos. • size_type erase(const key_type& k) – Erases the element whose key is k • void erase(iterator first, iterator last) – Erases all elements in a range • iterator find(const key_type& k) const – Finds an element whose key is k • Logarithmic complexity for insertion, remove, search Example Set Clients • Inventory struct StockItem { // barcode, name, amount }; • void print_inventory(std::ostream &os, const set<StockItem>& inventory) { set<StockItem>::iterator I; for (I = inventory.begin(); I != inventory.end(); ++I) { os << *I; } } Customer accounts class Customer { // ssn, account_number, last_name, first_name… }; int main() { set<Customer> customers; } Maps • Associative container that associates objects of type Key with objects of type Data – Sorted according to keys • Map – Stores (key, object) pairs – Unimodal: duplicate keys not allowed – AKA: table, associative array The STL Map Template • map() • map(const key_compare& comp) • pair<iterator, bool> insert(const value_type& x) – Inserts x into the map • iterator insert(iterator pos, const value_type& x) – Inserts x into the map, using pos as a hint to where it will be inserted • void insert(iterator, iterator) – Inserts a range into the map STL Map Template • void erase(iterator pos) – Erases the element pointed to by pos • size_type erase(const key_type& k) – Erases the element whose key is k • void erase(iterator first, iterator last) – Erases all elements in a range • iterator find(const key_type& k) – Finds an element whose key is k. • data_type& operator[](const key_type& k) – Returns a reference to the object that is associated with a particular key. – If the map does not already contain such an object, operator[] inserts the default object data_type() Map Usage Example struct ltstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; cout << "june: " << months["june"] << endl; typedef map<const char*, int, ltstr> MAP; Typedef MAP::iterator ITR; ++next; --prev; int main() { MAP months; cout << "Previous (in alphabetical order) is " << (*prev).first << “: “ << (*prev).second << endl; months["january"] = 31; months["february"] = 28; months["march"] = 31; months["april"] = 30; months["may"] = 31; months["june"] = 30; months["july"] = 31; months["august"] = 31; months["september"] = 30; months["october"] = 31; months["november"] = 30; months["december"] = 31; ITR cur = months.find("june"); ITR prev = cur; ITR next = cur; cout << "Next (in alphabetical order) is " << next->first “: “ << next->second << endl; }