1 / 40

Containers and Iterators

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.

harsha
Télécharger la présentation

Containers and Iterators

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CNS 3370 Containers and Iterators

  2. 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

  3. Sequences

  4. 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

  5. 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();

  6. Iterators • Generalization of a pointer • Overload at least operator!=, operator==, operator*, operator++, operator-> • Some overload operator--, operator[], pointer arithmetic

  7. 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

  8. Iterator Taxonomy • Input • Output • Forward • Bi-directional • Random Access

  9. 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

  10. 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; • }

  11. 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,“ “));

  12. 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

  13. Bi-directional Iterators • Can do everything a Forward Iterator can • Also support backwards traversal • operator--() • operator--(int) • reverse requires a Bi-directional Iterator

  14. Traversing a List BackwardsThe Hard Way list<T>::iterator p = lst.end(); while (p != lst.begin()) { --p; // “advances” backwards // process *p }

  15. A Better WayReverse Iterators list<T>::reverse_iterator p = lst.rbegin(); while (p != lst.rend()) { // process *p, then: ++p; // “advances” backwards }

  16. Random Access Iterators • Modeled after pointers • support Pointer Arithmetic in constant time • operator+, +=, -, -=, [], <, <=, >, >= • sort expects a Random Access Iterator

  17. Iterator TaxonomySummary “Functional” inheritance via duck typing (not via classes)

  18. 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

  19. What’s Wrong with this Picture? vector<int> v1; … // fill v1, then: vector<int> v2; copy(v1.begin(), v1.end(), v2.begin());

  20. 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

  21. 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

  22. 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)

  23. Insert Helper Functions • back_inserter • creates a back_insert_iterator • front_inserter • creates a front_insert_iterator • inserter • creates an insert_iterator

  24. 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));

  25. 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

  26. 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);

  27. Container Adapters Higher-level Containers that use Sequences

  28. 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

  29. 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

  30. 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)

  31. Associative Containers

  32. 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

  33. 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");

  34. // 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; }

  35. // Output: Alabama Georgia Tennessee found Alabama didn't find Michigan

  36. 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

  37. // Print the map: auto p = m.begin(); while (p != m.end()) { auto elem = *p++; cout << '{' << elem.first << ',’ << elem.second << "}\n"; } cout << endl;

  38. // 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

  39. 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

  40. 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

More Related