410 likes | 632 Views
CNS 3370. Containers and Iterators. Standard Containers. Sequences vector,deque,list,(string), forward_list Container Adapters queue, stack, priority_queue Associative Containers set, unordered_set map, unordered_map plus multi_ versions of each of the above. Sequences.
E N D
CNS 3370 Containers and Iterators
Standard Containers • Sequences • vector,deque,list,(string),forward_list • Container Adapters • queue, stack, priority_queue • Associative Containers • set, unordered_set • map, unordered_map • plus multi_ versions of each of the above
Most Sequences support... bool empty(); // use instead of size() == 0 size_t size(); void resize(size_t, T = T()); T& front(); T& back(); // Notforward_list void push_back(const T&); // Notforward_list void pop_back(); // Notforward_list
Restricted Sequence Functions // deque and list/forward_list only: void push_front(const T&); void pop_front(); //deque, vector and string only: T& at(size_type n); // range-checked T& operator[] shrink_to_fit();
Iterators • Generalization of a pointer • Overload at least operator!=, operator==, operator*, operator++, operator-> • Some overload operator--, operator[], pointer arithmetic
Implementing find • template<class Iterator, class T> • Iterator • find(Iterator start, Iterator past, const T& v) • { • while (start != past) • { • if (*start == v) • break; • ++start; • } • return start; • } • All algorithms are implemented in terms of iterators
Iterator Taxonomy • Input • Output • Forward • Bi-directional • Random Access
Input Iterators • Modeled after file input • Read-only access to elements • Single-pass, forward traversal • find expects an Input Iterator • it only needs to read through the data once
The Real Implementation of find(Name change only; uses Duck Typing) • template<class InputIterator, class T> • InputIterator • find(InputIterator start, InputIterator past, • const T& v) • { • while (start != past) • { • if (*start == v) • break; • ++start; • } • return start; • }
Output Iterators • Modeled after file output • Write-only access to elements • Single-pass, forward traversal • Example: ostream_iterator: copy(a, a+n, ostream_iterator<int>(cout,“ “));
Forward Iterators • Both read and write access • can be used as Input or Output Iterators • Multiple-pass, forward traversal • unique expects a Forward Iterator list<T>::iterator p = unique(lst.first(), lst.end()); • It needs 2 simultaneous, read/write iterators
Bi-directional Iterators • Can do everything a Forward Iterator can • Also support backwards traversal • operator--() • operator--(int) • reverse requires a Bi-directional Iterator
Traversing a List BackwardsThe Hard Way list<T>::iterator p = lst.end(); while (p != lst.begin()) { --p; // “advances” backwards // process *p }
A Better WayReverse Iterators list<T>::reverse_iterator p = lst.rbegin(); while (p != lst.rend()) { // process *p, then: ++p; // “advances” backwards }
Random Access Iterators • Modeled after pointers • support Pointer Arithmetic in constant time • operator+, +=, -, -=, [], <, <=, >, >= • sort expects a Random Access Iterator
Iterator TaxonomySummary “Functional” inheritance via duck typing (not via classes)
How do you Sort a Linked List? • Doesn’t provide a Random Access Iterator • Generic sort will fail on a list • Answer: • Provides its own sortmember function • Also merge, remove, and unique
What’s Wrong with this Picture? vector<int> v1; … // fill v1, then: vector<int> v2; copy(v1.begin(), v1.end(), v2.begin());
Iterator Modes • Iterators work in overwrite mode by default • Need an insert mode for cases like above • that calls the appropriate insert operation provided by the container
Insert IteratorsWrappers for Normal Iterators • Replace output calls (operator*, operator=, etc.) with appropriate insert function • back_insert_iterator • calls push_back • front_insert_iterator • calls push_front • insert_iterator • calls insert
Insert IteratorExampleCorrected vector<int> v1; … // fill v1, then: vector<int> v2; copy(v1.begin(), v1.end(), back_inserter(v2)); (But there is still a better way)
Insert Helper Functions • back_inserter • creates a back_insert_iterator • front_inserter • creates a front_insert_iterator • inserter • creates an insert_iterator
Stream Iterators • ostream_iterator • an Output Iterator copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, “ “)); • istream_iterator • an Input Iterator copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(v1));
Range-based Member FunctionsFor modifying sequences • insert, assign, erase, and constructors • Usually more efficient than the generic algorithm counterparts • Prefer over using copy • See range-based.cpp
The erase-remove Idiom • For erasing selected elements of a sequence • applies to vector, deque, string • for lists, use remove/remove_if • The idiom: • The remove algorithm reorders the sequence, moving the deleted elements to the end • returning an iterator to the first deleted element • c.erase(remove(beg, end, x), end); • c.erase(remove_if(beg, end, pred), end);
Container Adapters Higher-level Containers that use Sequences
Container Adapters • High-level abstract data types • queue, stack, priority_queue • They “adapt” sequences for specific uses • i.e., they use a sequence for implementation • stack & queue use deque by default • priority_queue uses a vector • can change the underlying sequence: stack<string, vector<string>> myStack; • No iterators are provided • they offer a more restricted interface
Restricted Interfaces • queue: • pushes at end, pops from front • front, back, push, pop • stack: • pushes and pops at front • top, push, pop • priority_queue: (See pq.cpp, pq2.cpp) • retrieves elements in priority order • you provide a strict weak ordering
Strict Weak Orderings (SWO) • priority_queue and ordered associative containers (set, map, multi_set, multi_map) require strict weak ordering comparators • behave like less< >( ) ( (which calls operator<( )) • never use <= or anything like it!!! • Definition: f(x,y) is a SWO if: • f(x,x) = false (irreflexive) • f(x,y) = !f(y,x) (anti-symmetric) • f(x,y) && f(y,z) => f(x,z) (transitive)
Associative Containers • Two “flavors” • Ordered • tree-based storage • O(log n) retrieval • set, multi_set, map, multi_map • Unordered • hashed-based storage • O(1) retrieval • unordered_set, unordered_map
Ordered Set Example #include <iostream> #include <set> #include <string> using namespace std; int main() { // Populate a set: set<string> s; s.insert("Alabama"); s.insert("Georgia"); s.insert("Tennessee"); s.insert("Tennessee");
// Print it out: auto p = s.begin(); while (p != s.end()) cout << *p++ << endl; cout << endl; // Do some searches: string key = "Alabama"; p = s.find(key); cout << (p != s.end() ? "found " : "didn't find ") << key << endl; key = "Michigan"; p = s.find(key); cout << (p != s.end() ? "found " : "didn't find ") << key << endl; }
// Output: Alabama Georgia Tennessee found Alabama didn't find Michigan
Map Example #include <iostream> #include <map> #include <string> using namespace std; int main() { // Insert some elements (two ways): map<string,string,greater<string>> m; m.insert(make_pair(string("Alabama"), string("Montgomery"))); m["Georgia"] = "Atlanta"; m["Tennessee"] = "Knoxville"; m["Tennessee"] = "Nashville"; // overwrites
// Print the map: auto p = m.begin(); while (p != m.end()) { auto elem = *p++; cout << '{' << elem.first << ',’ << elem.second << "}\n"; } cout << endl;
// Retrieve via a key: cout << '"' << m["Georgia"] << '"' << endl; cout << m.size() << endl; cout << '"' << m["Texas"] << '"' << endl; cout << m.size() << endl; } // Output: {Tennessee,Nashville} {Georgia,Atlanta} {Alabama,Montgomery} "Atlanta" 3 "" 4
Word Count Example • Shows the conciseness of map’s design • Count the number of each word in a text file • wordcount.cpp • output in wordcount-gettysburg.out
map and set use SWOs! • Necessary to maintain proper order in the underlying tree data structure • They test for equivalence, not equality, to maintain uniqueness • x and y are equivalentiff !cmp(x,y) && !cmp(y,x) • i.e., neither precedes the other • Example: • swo.cpp • ignores non-alpha characters in strings