Containers Iterators STL Containers Container object that holds
Containers & Iterators
STL Containers • Container: object that holds other objects • Sequence containers in STL: • vector: dynamic array • deque: double-ended queue • list: linear list • Associative containers: permit efficient retrieval of values based on keys – elements referenced by key, not position • Unique keys – no two elements can have equivalent keys • map: key-value pairs, like a dictionary • set: no duplicate elements
Iterators • Objects that act like pointers • increment, dereference • Use to cycle through container's elements • Depending on type of iterator, may permit: • moving forward and/or backward through elements • retrieve elements • modify elements • Declare using iterator type defined by container • Example: vector<int>: : iterator iter =. . . ;
vector Review vector<int> v; // empty vector<int> vec(1000); // 1000 elements, all initialized to 0 cout << vec. size() << endl; // 1000 vec. clear(); // remove all elements cout << vec. size() << endl; // 0
vector • resize() for vectors: • specify size only (elements initialized to 0) • Specify size and value for new elements • new elements added at end of vector • if vector shrinks, elements removed from end vector<int> v; // empty v. resize(10, 0); // Add 10 new elements to end, set all of them to 0 v. resize(5); v. resize(8, 1); // remove 5 elements from end // add three new elements to end, all initialized to 1 • pop_back(): remove element from end v. pop_back();
vector iteration • begin() iterator points to 1 st element of vector • end() iterator points one position past end of vector for(vector<int>: : iterator it = my. Vector. begin(); it != my. Vector. end(); it++) cout << *itr << endl; begin() 120 end() 42 3 -9 16
vector • front(): return reference to first element • back(): return reference to last element • insert(): add element at specified position • vec. insert(vec. begin() + n, element); // Add element at index n • vec. insert(vec. begin() + n; num. Copies, element); // add multiple copies at index n • pop_back(): delete last element vector<int> v(5, 3); // 5 elements with value 3 v. push_back(7); int num = v. back(); // 7 v. pop_back(); // remove 7 from end v. insert(v. begin(), 9); // add 9 at beginning of vector
vector • begin(): returns iterator pointing to first element • end(): returns iterator pointing past the end of the vector • doesn't point to an element in vector (don't dereference) • erase(): remove a single element or range of elements from vector • • erase(iterator): iterator points to element to remove erase(iterator start, iterator end): remove elements in range [start, end) invalidates iterators pointing to or after removed element(s) returns iterator pointing at element following last element erased vec. erase(vec. begin() + 3); // remove element at index 3 vec. erase(vec. begin(), vec. begin() + 2); // erase first two elements
vector • empty(): returns true if vector is empty, false otherwise • insert(): add new element(s) at specified position • vec. insert(vec. begin() + n, element); // add element at index n • vec. insert(vec. begin() + n, num. Copies, element); // add num. Copies at index n • invalidates existing iterators vector<int> vec(3, 50); // [50, 50] vec. insert(vec. begin() + 1, 100); // add 100 at index 1: [50, 100, 50] vec. insert(vec. begin() + 2, 2, 40); // [50, 100, 40, 50]
vector<string> v; v. push_back("hello"); v. push_back("bye"); vector<string>: : iterator it = v. begin(); cout << it length() << endl;
Iterating Backwards • To traverse container's elements in reverse order, use a reverse_iterator • For a reverse_iterator object: ++rev. Iterator moves to the previous element • rbegin(), rend() for(vector<int>: : reverse_iterator it = vec. rbegin(); it != vec. rend(); it++) cout << *it << end; rbegin() rend() 18 -4 522 17
set • set: represents an unordered collection without duplicates • efficient insertion and removal, determining if element is in set • insert(), erase(), count() • count(): returns 1 if element in set, 0 otherwise • elements must be comparable using < • underlying implementation: binary search tree set<int> set 1; set 1. insert(120); // {120} set 1. insert(32); // {32, 120} set 1. insert(4); // {4, 32, 120} set 1. insert(32); // {4, 32, 120} (no dupes) if(set 1. count(32)) cout << "32 is in the set" << endl; cout << set 1. size() << endl; // 3 set 1. clear(); // removes all elements
set iterator set<int> my. Set =. . . ; for(set<int>: : iterator it = my. Set. begin(); it != my. Set. end(); it++) cout << *it << endl; • The set's elements are traversed in sorted (increasing) order • Example: #include<set> #include<cstdlib> set<int> rand. Nums; for(int k = 0; k < 10; k++) rand. Nums. insert(rand() % 100); // print random numbers in sorted order for(set<int>: : iterator it = random. Nums. begin(); it != random. Nums. end(); it++) cout << *it << " ";
set • Iterate over elements in a set in a specified range • lower_bound(lower): returns iterator to first element >= lower • upper_bound(upper): returns iterator to first element > upper • To iterate over values in range [lower, upper]: for(set<int>: : iterator it = my. Set. lower_bound(100); it != my. Set. upper_bound(200); it++) { cout << *it << endl; • If set contains the odd numbers from 3 to 301, the loop will print 101, 103, . . . , 199
pair • parameterized helper class • pair object holds two values of any type: pair<Type 1, Type 2> • two fields: first (of Type 1), second (of Type 2) • defined in <utility> pair<int, string> p 1; p 1. first = 312; p 1. second = "I love C++"; pair<int, string> p 2 = make_pair(422, "I love Java");
set Methods Method Description set<T> (iterator start, iterator stop) Constructs set containing copies of elements in range [start, stop). Duplicates are discarded. Elements are sorted. Accepts iterator from any source. set<int> the. Set(vec. begin(), vec. end()); set<T>() Constructs empty set<T>(const set<T>& other) Copy constructor set<int> set 2 = set 1; size_type size() const Returns number of elements in the set. int num = set 1. size(); bool empty() const Returns true if set is empty, false otherwise iterator begin() Returns an iterator to the start of the set<int>: : iterator it = set 1. begin(); pair<iterator, bool> insert(const T& value) void insert(iterator begin, iterator end) first version: inserts value into set, returning a pair which contains an iterator to the element and true if value was inserted, false if it was already in set. second version: inserts range of elements into set, ignoring duplicates.
set Methods Method Description void clear() Removes all elements iterator end() Returns an iterator find(const T& elt) Returns an iterator to specified element if it exists, and end otherwise size_type erase(const T& elt) void erase(iterator it) void erase(iterator start, iterator stop) if(my. Set. erase(0)) {. . . // 0 erased my. Set. erase(my. Set. begin()); my. Set. erase(my. Set. begin(), my. Set. end()); Removes an element from set. First version: 1 returned if element removed, 0 otherwise Second: removes element pointed at by it Third: Erases elements in range [start, stop) iterator lower_bound(const T& value) Returns iterator to first element >= value iterator upper_bound(const T& value) Returns iterator to first element > value
map key-value pairs map<string, string> dict; dict["thanks"] = "an expression of gratitude";
map • mapping between set of keys and set of values • elements are unordered – cannot be retrieved by position, only by key • implemented using balanced binary tree • keys must be comparable using < • keys are unique – no two key-value pairs in map may have same key • Useful operations: • • insert a key-value pair membership: check whether a key is in the map get value associated with a key remove a key-value pair
map: inserting elements • my. Map[key] = value; // add (key, value) to map<string, int> my. Map; // empty map my. Map["apple"] = 2; //insert ("apple", 2) in my. Map["elephant"] = 3; • square brackets can also be used to retrieve value associated with key: cout << my. Map["apple"] << endl; // 2 cout << my. Map["laugh"] << endl; // adds ("laugh", 0) and prints 0 • find(): takes key and returns iterator that points to pair with that key, or end() if key doesn't exist in map<string, int>: : iterator it = my. Map. find("laugh"); if(it == my. Map. end()) cout << "key is not in map" << endl;
map iterator • Dereferencing a map iterator produces a pair of type pair<const Key. Type, value. Type> • Keys in a map cannot be modified, but they can be removed. Value can be modified. map<string, int>: : iterator it = my. Map. find("laugh"); if(it == my. Map. end()) Is key in map? cout << "key is not in map" << endl; else cout << "Key " << it first << " has value " << it second << endl; • To loop over a map: for(map<string, int>: : iterator it = my. Map. begin(); it != my. Map. end(); it++) cout << it first << ": " << it second << endl; • key-value pairs traversed in increasing sorted order of key (alphabetical order in our example) apple: 2 elephant: 3 laugh: 0
map • To remove an element with a specified key: my. Map. erase(key); • To remove all elements from map: clear() • Number of elements in map: size() • How to add a key-value pair: map<string, string> map 1; map 1["ee 312"] = "happy"; map 1["ee 312"] = "sad"; // map 1 is {("ee 312", "sad")} map<string, string> map 2; map 2. insert(make_pair("ee 312", "happy")); map 2. insert(make_pair("ee 312", "sad")); // map 2 is {("ee 312", "happy")} insert will not insert pair if a pair with the specified key is already in the map.
map: insert() • A map stores a unique set of keys • insert returns a value of type pair<iterator, bool> • bool value: true if key-value pair inserted into map, false if key already existed in map • iterator: points to key-value pair in map with specified key, whether or not it was newly added • Using brackets to add a key-value pair often preferable pair<map<string, int>: : iterator, bool> result = my. Map. insert(make_pair("hi", 2)); if(!result. second) // if insertion failed, bool value is false result. first second = 2; iterator points to key-value pair with key "hi" // update the value assigned to key update the second entry in the key-value pair to 2
map Example • Map a string to a set of synonyms // Map of <string, set<string>> map<string, set<string> > pairs; set<string> s 1; s 1. insert("hello"); s 1. insert("hi ya"); pairs["greeting"] = s 1; set<string> s 2; s 2. insert("bye"); s 2. insert("later"); pairs["farewell"] = s 2;
map Example • Map a string to a set of synonyms for(map<string, set<string> >: : iterator it = pairs. begin(); it != pairs. end(); it++) { cout << "Key: " << it->first << endl; for(set<string>: : iterator it 2 = (it->second). begin(); it 2 != (it->second). end(); it 2++) { cout << *it 2 << " "; } cout << endl; Output: } Key: farewell bye later Elements in pairs: Key: greeting ("greeting", {"hello", "hi ya"}) hello hi hi ya ("farewell", {"bye", "later"})
- Slides: 25