420 likes | 517 Views
Associative Containers. Gordon College Prof. Brinton. STL - Assoc. Containers. Set The key is the data set<int> intSet; set<string> keyword; set<time24> timeSet; To support the STL container - set; the programmer must overload the == operator and < operator by comparing
E N D
Associative Containers Gordon College Prof. Brinton
STL - Assoc. Containers • Set • The key is the data set<int> intSet; set<string> keyword; set<time24> timeSet; To support the STL container - set; the programmer must overload the == operator and < operator by comparing the key field and giving a Boolean result.
STL - Assoc. Containers • Map • Stores entries as key-value pair. • In a pair, the first component is the key; the second is the value. Each component may have a different data type. map<int, record> studentFile; studentFile[2343554] = new studentFile; studentFile[2343554].addToBalance(112);
Set and Map • Both containers do not allow duplicate keys. • Multiset and multimap (also STL containers) allow duplicate keys)
STL Set include <set> • Constructors: set(); default - empty set set(T *first, T *last); use pointers or iterators Examples: set<int> first; // empty set of ints int myints[]= {10,20,30,40,50}; set<int> second (myints,myints+5); // pointers set<int> third (second); // a copy of second set<int> fourth (second.begin(), second.end()); // iterators into second
STL Set include <set> • Operations: bool empty() const; void clear(); int size() const; int count(const T& key) const; //return either 1 or 0 iterator find(const T& key); const_iterator find(const T& key) const; // returns either an iterator or end() NOTE: STL Associative Containers iterators do access the elements in the defined order.
STL Set include <set> • Operations: pair<iterator, bool> insert(const T& key); // this return a pair object Example: string t[]={"this","is","a","test"}; set<string> s(t,t+4); pair<set<string>::iterator,bool> result = s.insert("OK"); (result.second)?cout << "TRUE":cout << "FALSE"; result = s.insert("OK"); (result.second)?cout << "TRUE":cout << "FALSE"; Result: TRUEFALSE
STL Set include <set> • Operations: void erase ( iterator position ); void erase ( iterator first, iterator last ); size_type erase ( const key_type& x ); //returns either 1 or 0 void swap ( set<Key,Compare,Allocator>& st ); • Obtaining the bounds: pair<iterator,iterator> equal_range ( const key_type& x ) const; iterator lower_bound ( const key_type& x ) const; //iterator of first value not < x iterator upper_bound ( const key_type& x ) const; //iterator of first value > x
STL Set include <set> • Iterators: iterator begin(); const_iterator begin(const); iterator end(); const_iterator end(const);
Set operators 3 8 11 15 2 1 4 6 • Union setC = setA + setB; setC = 1 2 3 4 5 6 7 8 11 15 • Intersection A*B setC = setA * setB; setC = 3 5 7 8 11 • Difference setC = setA - setB; setC = 1 4 3 8 11 7 5 7 5
Map include <map> • Operations are like set’s operations • swap • begin • end • size • empty • operator[] //unlike set • find • erase See the following examples
#include <string.h> #include <iostream> #include <map> using namespace std; int main() { map<int, string> Employees; Employees[5234] = "Mike C."; Employees[3374] = "Charlie M."; Employees[1923] = "David D."; Employees[7582] = "John A."; Employees[5328] = "Peter Q."; cout << "Employees[3374]=" << Employees[3374] << endl << endl; cout << "Map size: " << Employees.size() << endl; for( map<int,string>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; } }
Employees[3374]=Charlie M. Map size: 5 1923: David D. 3374: Charlie M. 5234: Mike C. 5328: Peter Q. 7582: John A. #include <string.h> #include <iostream> #include <map> using namespace std; int main() { map<int, string> Employees; Employees[5234] = "Mike C."; Employees[3374] = "Charlie M."; Employees[1923] = "David D."; Employees[7582] = "John A."; Employees[5328] = "Peter Q."; cout << "Employees[3374]=" << Employees[3374] << endl << endl; cout << "Map size: " << Employees.size() << endl; for( map<int,string>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; } }
#include <string.h> #include <iostream> #include <map> using namespace std; int main() { map<string, int> Employees; Employees["Mike C."] = 5234; Employees["Charlie M."] = 3374; Employees.insert(pair<string,int>("David D.",1923)); Employees.insert(map<string,int>::value_type("John A.",7582)); Employees.insert(make_pair("Peter Q.",5328)); cout << "Map size: " << Employees.size() << endl; for( map<string, int>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; } }
Map size: 5 Charlie M.: 3374 David D.: 1923 John A.: 7582 Mike C.: 5234 Peter Q.: 5328 #include <string.h> #include <iostream> #include <map> using namespace std; int main() { map<string, int> Employees; Employees["Mike C."] = 5234; Employees["Charlie M."] = 3374; Employees.insert(pair<string,int>("David D.",1923)); Employees.insert(map<string,int>::value_type("John A.",7582)); Employees.insert(make_pair("Peter Q.",5328)); cout << "Map size: " << Employees.size() << endl; for( map<string, int>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; } }
struct cmp_str { bool operator()(char const *a, char const *b) { return strcmp(a, b) < 0; } }; int main() { map<char *, int, cmp_str> Employees; Employees["Mike C."] = 5234; Employees["Charlie M."] = 3374; Employees.insert(pair<char *,int>("David D.",1923)); Employees.insert(map<char *,int>::value_type("John A.",7582)); Employees.insert(make_pair((char *)"Peter Q.",5328)); cout << "Map size: " << Employees.size() << endl; for( map<char *, int, cmp_str>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; } }
Map size: 5 Charlie M.: 3374 David D.: 1923 John A.: 7582 Mike C.: 5234 Peter Q.: 5328 Could this be ordered differently? struct cmp_str { bool operator()(char const *a, char const *b) { return strcmp(a, b) < 0; } }; int main() { map<char *, int, cmp_str> Employees; Employees["Mike C."] = 5234; Employees["Charlie M."] = 3374; Employees.insert(pair<char *,int>("David D.",1923)); Employees.insert(map<char *,int>::value_type("John A.",7582)); Employees.insert(make_pair((char *)"Peter Q.",5328)); cout << "Map size: " << Employees.size() << endl; for( map<char *, int, cmp_str>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; } }
Map details • Associative Arrays M[“Computer Science”] = 20; Keys are unique therefore: M[“Computer Science”] = 26; replaces the value in the tree for CS.
Map details • Creating a map: #include <map> int main() { map<string, double> A; …
Map Details • [ ] operator Steps • Search the for map for key • If key found, return a reference to the value object associated with key. • If key not found, create a new object of type value associated with key, and return a reference to that.
Map Details • [ ] operator int salary = Employee[“Jack Smith”]; Caution: this will create a new tree entry if it doesn’t exist and assign 0 to variable salary
Map Details • [ ] operator Better technique: if (( itr = Employee.find(“Jack Smith”)) == Employee.end()) cout << “ the employee does not exist.” << endl; Else cout << “Employee Salary: “ << itr->second << endl;
Map Details • Pair Class 1. Contains two public members, first and second 2. Store key/value association itr->first itr->second
Map Details • Pair Class Easiest way to construct pair: pair<string, int> a; a = make_pair(string(“Jack Smith”), int(100000));
Map Details • Element requirements: Each key and value must be assignable (an assignment operator which performs a “deep copy” Deep copy target of the assignment should be equal but independent of the source a = b; the value of a should match b - however if you change a it should not affect b (and vice versa) Note: if we talking about a linked list then a shallow copy would have two pointers pointing to the same list.
Map Details • Element requirements: Also each key should adhere to “weak ordering”: 1. A<A is false 2. Equality can be determined with (!(A<B) && !(B<A)) Note: only using the less than operator 3. If A<B and B<C then A<C must be true int, char, double, etc. (built-in types) are strict weak ordered
Map Details • Element requirements: value type used must have a defined default constructor. map <int, bigNumber> The built in types have a type of default constructor: map<int, string>
Multimap/Multiset begin end rbegin rend clear empty count equal_range lower_bound upper_bound insert erase find max_size operator= size swap
Multimap/Multiset Detailsequal_range multiset<int>::iterator it; pair<multiset<int>::iterator,multiset<int>::iterator> ret; int myints[]= {77,30,16,2,30,30}; multiset<int> mymultiset (myints, myints+6); // 2 16 30 30 30 77 ret = mymultiset.equal_range(30); for (it=ret.first; it!=ret.second; ++it) ++(*it); // 2 16 31 31 31 77
(2) 12 (5) 7 (1) 20 4 9 30 (3) (2) (1) Multimap/Multiset Details • How is multiset implemented? Multiset: BST - with integer value representing each occurrence of the element insert {find - if not present create node else increment count} erase {remove node and report back count} HOW WOULD THESE BE HANDLED? clear empty count find size
(“Tom” -> “Jack” -> “Joe”) 12 (“Tom”) 7 20 (“Jack” -> “Joe”) 4 9 30 (“Emma”) (“Jack”) (“Jack” -> “Joe”) Multimap/Multiset Details • How is multimap implemented? Multimap: BST - with list or map as the node’s payload insert {find - if not present create node else add value to list/set} erase {remove node and report back count} HOW WOULD THESE BE HANDLED? clear empty count find size There is not guarantee as to order of duplicates