CNS 3370 Containers and Iterators Standard Containers Sequences

  • Slides: 40
Download presentation
CNS 3370 Containers and Iterators

CNS 3370 Containers and Iterators

Standard Containers Sequences vector, deque, list, (string), forward_list Container Adapters queue, stack, priority_queue Associative

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

Sequences

Most Sequences support. . . bool empty(); // use instead of size_t size(); void

Most Sequences support. . . bool empty(); // use instead of size_t size(); void resize(size_t, T = T()); T& front(); T& back(); // Not void push_back(const T&); // Not void pop_back(); // Not size() == 0 forward_list

Restricted Sequence Functions // deque and list/forward_list only: void push_front(const T&); void pop_front(); //deque,

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

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)

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

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

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 Input. Iterator,

The Real Implementation of find (Name change only; uses Duck Typing) template<class Input. Iterator, class T> Input. Iterator find(Input. Iterator start, Input. Iterator 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:

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

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--()

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 Backwards The Hard Way list<T>: : iterator p = lst. end();

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

A Better Way Reverse Iterators list<T>: : reverse_iterator p = lst. rbegin(); while (p

A Better Way Reverse 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+, +=,

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

Iterator Taxonomy Summary “Functional” inheritance via duck typing (not via classes)

Iterator Taxonomy Summary “Functional” inheritance via duck typing (not via classes)

How do you Sort a Linked List? Doesn’t provide a Random Access Iterator Generic

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 sort member function Also merge, remove, and unique

What’s Wrong with this Picture? vector<int> v 1; … // fill v 1, then:

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

Iterator Modes Iterators work in overwrite mode by default Need an insert mode for

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 Iterators Wrappers for Normal Iterators Replace output calls (operator*, operator=, etc. ) with

Insert Iterators Wrappers 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 Iterator Example Corrected vector<int> v 1; … // fill v 1, then: vector<int>

Insert Iterator Example Corrected vector<int> v 1; … // fill v 1, then: vector<int> v 2; copy(v 1. begin(), v 1. end(), back_inserter(v 2)); (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 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(v 1. begin(), v 1. end(), ostream_iterator<int>(cout, “

Stream Iterators ostream_iterator an Output Iterator copy(v 1. begin(), v 1. end(), ostream_iterator<int>(cout, “ “)); istream_iterator an Input Iterator copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(v 1));

Range-based Member Functions For modifying sequences insert, assign, erase, and constructors Usually more efficient

Range-based Member Functions For 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,

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 Higher-level Containers that use Sequences

Container Adapters High-level abstract data types queue, stack, priority_queue They “adapt” sequences for specific

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>> my. Stack; No iterators are provided they offer a more restricted interface

Restricted Interfaces queue: pushes at end, pops from front, back, push, pop stack: pushes

Restricted Interfaces queue: pushes at end, pops from front, back, push, pop stack: pushes and pops at front top, push, pop priority_queue: (See pq. cpp, pq 2. 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 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

Associative Containers

Associative Containers Two “flavors” Ordered tree-based storage O(log n) retrieval set, multi_set, map, multi_map

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()

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

// Print it out: auto p = s. begin(); while (p != s. end())

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

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

Map Example #include <iostream> #include <map> #include <string> using namespace std; int main() {

Map Example #include <iostream> #include <map> #include <string> using namespace std; int main() { // Insert some elements (two ways): map<string, greater<string>> m; m. insert(make_pair(string("Alabama"), string("Montgomery"))); m["Georgia"] = "Atlanta"; m["Tennessee"] = "Knoxville"; m["Tennessee"] = "Nashville"; // overwrites

// Print auto p = while (p auto cout the map: m. begin(); !=

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

} // Retrieve via a key: cout << '"' << m["Georgia"] << '"' <<

} // 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 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

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 equivalent iff !cmp(x, y) && !cmp(y, x) i. e. , neither precedes the other Example: swo. cpp ignores non-alpha characters in strings