170 likes | 182 Views
STL Containers. Some other containers in the STL. Today’s Questions. What is an associative container? Why would I use an associative container over a sequential container? What is an unordered associative container? Why would I use an unordered associative container over an ordered one?.
E N D
STL Containers Some other containers in the STL
Today’s Questions • What is an associative container? • Why would I use an associative container over a sequential container? • What is an unordered associative container? • Why would I use an unordered associative container over an ordered one?
Motivating Associative Containers • How can we find a value in a std::vector? • Option 1:
Motivating Associative Containers • How can we find a value in a std::vector? • Option 1: std::find – which has O(n) complexity • Option 2: sort the container, then search efficiently • Difficult/error prone • What data structure is inherently ordered?
Motivating Associative Containers • How can we find a value in a std::vector? • Option 1: std::find – which has O(n) complexity • Option 2: sort the container, then search efficiently • Difficult/error prone • What data structure is inherently ordered? • From ECE244: a binary search tree (BST) • STL equivalent: std::map
std::map • Benefits • Self-balancing BST • Guaranteed O(log n): find, insert, and erase • std::map uses std::pair • First: key • Second: value • ECE244 Lab 5 – Domain Name Lookup • Key: domain name as an std::string • Value: IP address as an int • std::pair<std::string, int>
std::mapInsertion Example #include <map> #include <string> intmain(){ std::map<std::string,int>dns_lookup; // Option 1 std::pair<std::string,int>google("www.google.com",215183441); dns_lookup.insert(google); // Option 2 auto apple =std::make_pair("www.apple.com",398782126); dns_lookup.insert(apple); // Option 3 dns_lookup.insert(std::make_pair("www.utoronto.ca",918567265)); } Include the map container Create the map, specifying the key and value Create pair first (constructor), then insert Create pair first (helper function), then insert Pass pair directly to insert map_insert.cpp
Searching std::map #include <iostream> #include <map> #include <string> intmain(){ std::map<std::string,int>dns_lookup; dns_lookup.insert(std::make_pair("www.google.com",215183441)); dns_lookup.insert(std::make_pair("www.apple.com",398782126)); dns_lookup.insert(std::make_pair("www.utoronto.ca",918567265)); autoit =dns_lookup.find("www.apple.com"); if(it !=dns_lookup.end()){ std::cout<< it->first <<": "<< it->second <<"\n"; } it =dns_lookup.find("www.microsoft.com"); if(it ==dns_lookup.end()){ std::cout<<"Could not find www.microsoft.com\n"; } } What should we use to search, key or value? map_lookup.cpp
Searching std::map #include <iostream> #include <map> #include <string> intmain(){ std::map<std::string,int>dns_lookup; dns_lookup.insert(std::make_pair("www.google.com",215183441)); dns_lookup.insert(std::make_pair("www.apple.com",398782126)); dns_lookup.insert(std::make_pair("www.utoronto.ca",918567265)); autoit =dns_lookup.find("www.apple.com"); if(it !=dns_lookup.end()){ std::cout<< it->first <<": "<< it->second <<"\n"; } it =dns_lookup.find("www.microsoft.com"); if(it ==dns_lookup.end()){ std::cout<<"Could not find www.microsoft.com\n"; } } How do we check if the key was found? How do we check if the key was not found? map_lookup.cpp
Searching std::map #include <iostream> #include <map> #include <string> intmain(){ std::map<std::string,int>dns_lookup; dns_lookup.insert(std::make_pair("www.google.com",215183441)); dns_lookup.insert(std::make_pair("www.apple.com",398782126)); dns_lookup.insert(std::make_pair("www.utoronto.ca",918567265)); autoit =dns_lookup.find("www.apple.com"); if(it !=dns_lookup.end()){ std::cout<< it->first <<": "<< it->second <<"\n"; } it =dns_lookup.find("www.microsoft.com"); if(it ==dns_lookup.end()){ std::cout<<"Could not find www.microsoft.com\n"; } } www.apple.com: 398782126 The iterator points to the entire node in the map, which is an std::pair! Could not find www.microsft.com map_lookup.cpp
Iterating Over an std::map intmain(){ std::map<std::string,int>dns_lookup; dns_lookup.insert(std::make_pair("www.google.com",215183441)); dns_lookup.insert(std::make_pair("www.apple.com",398782126)); dns_lookup.insert(std::make_pair("www.utoronto.ca",918567265)); for(autoit =dns_lookup.begin(); it !=dns_lookup.end();++it){ std::cout<< it->first <<": "<< it->second <<"\n"; } } Use iterators and a for loop to print out all the nodes in the std::map. www.apple.com: 398782126 www.google.com: 215183441 www.utoronto.ca: 918567265 map_loop.cpp
Accessing Elements in std::map • operator[key] • Returns a reference to the value • If key does not exist, will insert a new one • Helpful as a replacement for insert • Dangerous for lookup
What will this output? std::map<std::string,int>dns_lookup; dns_lookup.insert(std::make_pair("www.google.com",215183441)); dns_lookup.insert(std::make_pair("www.apple.com",398782126)); //dns_lookup.insert(std::make_pair("www.utoronto.ca", 918567265)); dns_lookup["www.utoronto.ca"]=918567265; std::cout<<"Google: "<<dns_lookup["www.google.com"]<<"\n"; std::cout<<"Microsoft: "<<dns_lookup["microsoft.com"]<<"\n"; std::cout<<"Apple: "<<dns_lookup["www.apple.com"]<<"\n"; std::cout<<"Ebay: "<<dns_lookup.["ebay.ca"]<<"\n"; Google: 215183441 Microsoft: 0 Apple: 398782126 Ebay: 0 Missing keys inserted with default values! map_access.cpp
Duplicate Keys with Map #include <map> #include <iostream> intmain(){ std::map<std::string,float>salary_database; salary_database.insert(std::make_pair("John Smith",45000)); salary_database.insert(std::make_pair("Mary Sue",90000)); salary_database.insert(std::make_pair("Gary Stu",40000)); salary_database.insert(std::make_pair("John Smith",30000)); auto it =salary_database.find("John Smith"); std::cout<< it->first " earns $" it->second <<"\n"; } Key exists. Not inserted! John Smith earns $45000
Handling Duplicate Keys with Multimap #include <map> #include <iostream> intmain(){ std::multimap<std::string,float>salary_database; salary_database.insert(std::make_pair("John Smith",45000)); salary_database.insert(std::make_pair("Mary Sue",90000)); salary_database.insert(std::make_pair("Gary Stu",40000)); salary_database.insert(std::make_pair("John Smith",30000)); autoit =salary_database.find("John Smith"); std::cout<< it->first " earns $" it->second <<"\n"; } An insertion takes place – this is a multimap. Only one entry is (arbitrarily) returned.
Looking Up Multiple Values in MultiMap #include <map> #include <iostream> intmain(){ std::multimap<std::string,float>salary_database; salary_database.insert(std::make_pair("John Smith",45000)); salary_database.insert(std::make_pair("Mary Sue",90000)); salary_database.insert(std::make_pair("Gary Stu",40000)); salary_database.insert(std::make_pair("John Smith",30000)); auto range =salary_database.equal_range("John Smith"); for(auto it =range.first; it !=range.second;++it){ std::cout<< it->first " earns $" it->second <<"\n"; } } equal_range returns a std::pair<iterator, iterator> that gives the range of entries matching the key “John Smith” John Smith earns $30000 John Smith earns $45000