. STL: C++ Standard Library (continued). STL Iterators u Iterators are allow to traverse sequences u...
-
Upload
ava-provence -
Category
Documents
-
view
237 -
download
0
Transcript of . STL: C++ Standard Library (continued). STL Iterators u Iterators are allow to traverse sequences u...
STL Iterators Iterators are allow to traverse sequences Methods
operator* operator-> operator++, and operator—
Different types of iterators - to support read, write and random access
Containers define their own iterator types Changing the container can invalidate the iterator
Iterator Types
Output: write only and can write only once Input: read many times each item Forward: supports both read and write Bi-directional: supports also decrement Random: supports random access (just like C pointer)
Output Input Forward Bi-directional Random
Read x = *i x = *i x = *i x = *i
Write *i = x *i = x *i = x *i = x
Iteration ++ ++ ++ ++, -- ++, --, +, -, +=, -=
Comparison ==, != ==, != ==, != ==, !=, <, >, <=, >=
Iterators & Containers
Bidirectional iterators: list, map, set
Random access iterators: vector, deque
Input/output/forward iterators: iostreams
Iterators & Containers
Every STL container T provides:
class T {
…
typedef … iterator // iterator type T
iterator begin(); // first element of the container
iterator end(); // element after last of the container
};
Iterators & Containers
Typical code will look like:
Container C
…
Container::iterator i
for( i = C.begin(); i != C.end(); i++)
// do something with *i
Iterators & Containers
Iterators allow to access/modify elements
Container C;Container::iterator i,j;
C.insert(i,x) – insert x before i C.insert(i,first,last)
– insert elements in [first,last) before i C.erase(i) – erase element i points to C.erase(i,j)
– erase elements in range [i,j)
Iterator validity
When working with iterators, we have to remember that their validity can change
Whats wrong with this code?
Container C;C::iterator i;for( i = C.begin(); i != C.end(); i++ )
if( f( *i ) ) // some test
C.erase(i); // remove this element
Iterator validity
Second try…Container C;
C::iterator i = C.begin();
while( i != C.end() )
{
C::iterator j = i++;
if( f( *j ) ) // some test
C.erase(j); // remove this element
}
Works for set, map, list, not vector or deque
Iterator Validity
Third try…Container C;
C::iterator i;
for(i = C.begin(); i != C.end(); i++ )
if( f( *i ) ) // some test
i= C.erase(i); // erase returns the iterator for the next element in the container.
Still does not work for vector.
Iterators and Map
Suppose we work with
map<string,int> dictionary;
map<string,int>::iterator i;
…
i = dictionary.begin();
What is the type of *i ?
Iterators and Map
Every STL container type Container defines
Container::value_type
Type of elements stored in container
This is the type returned by an iteratorContainer::value_type
Container::iterator operator*();
Iterators and Map
Ok, so what type of elements does a map return (what is value_type of map) ?
Recall map<KeyType,DataType> keeps pairs
KeyType key – “key” of entry DataType value – “value” of entry
Pairs
template< class T1, class T2>
struct pair {
typedef T1 first_type;
typedef T2 first_type;
T1 first;
T2 second;
pair( const T1& x, const T2& y )
: first(x), second(y)
{}
};
Map value_type
template< class Key, class T,
class Cmp = less<Key> >
class map {
public:
typedef pair<const Key, T> value_type;
typedef Key key_type;
typedef T data_type;
typedef Cmp key_compare;
};
Using map iterator
map<string,int> dict;
…
map<string,int>::iterator i;
for( i = dict.begin();
i != dict.end();
i++ )
{
cout << i->first << “ “
<< i->second << “\n”;
}
[See dictionary.cpp]
Iterators and Assoc. Containers
Additional set of operations: iterator C::find(key_type const& key)
Return iterator to first element with key. Return end() if not found
iterator C::lower_bound(key_type const& key)
Return iterator to first element greater or equal to key
iterator C::upper_bound(key_type const& key)
Return iterator to first element greater than key
Iterators & Streams
Can access iostreams through iterators:istream_iterator<string> in(cin);
istream_iterator<string> endOfInput;
ostream_iterator<string> out(cout);
while( in != endOfInput )
{
string s = *in++;
*out++ = s;
*out++ = “ “;
}
see useStreamIterators.cpp
Inserters
istream_iterator<string> in(cin);
istream_iterator<string> endOfInput; vector<string> vect;
back_insert_iterator<vector<string> >
back(vect);
// copy input words into vector…
while( in != endOfInput )
*back++ = *in++;
// same as: vect.push_back(*in++)
Inserters
Inserters are output iterators back_insert_iterator<C>( C& c)
Insert at back of c front_insert_iterator<C>( C& c)
Insert at front of c insert_iterator<C,Iter>(C& c, Iter i)
Insert at just before i
Allow to write into containers in generic algorithms
Do-it-yourself iterators
You can create iterators
Check list: Define the appropriate operators Ensure copy constructor/operator Define the right typedefs
use inheritance from iterator<..> class
[See TokenIterator.h]
Sequence Adapters
Adapters of basic containers Very easy, but limited interface
stack<T,Seq> provides push, pop, top, size and empty
queue<T,Seq> also provides back
priority_queue<T,Seq,Cmp> provides same interface as stack uses a compare function object
Container summary
[] List ops Front ops Back ops Iterators
vector const n+ const+ Random
list const const const Bi-direct
deque const n const const Random
stack const
queue const const
priority_queue log(n) log(n)
map log(n) log(n)+ Bi-direct
set log(n)+ Bi-direct
Algorithms Overview
Sequence operations Non modifying: for_each, find, count, search, mismatch, equal
Modifying: transform, copy, swap, replace, fill, generate, remove, unique, reverse, rotate, random_shuffle
Sorted sequences operations sort, lower_bound, upper_bound, equal_range, binary_search, merge, includes, set_union, intersection, set_difference, set_symmetric_difference
Algorithms
Most STL algorithms works on sequences Sequences are passed as two iterators:
beginning element element one after last
Algorithms depend on iterator type
not on container type
p q
sequence [p,q)
Copy
template< class In, class Out>
Out copy(In first, In last, Out res)
{
while (first != last)
*res++ = *first++;
return res;
}
See useCopy.cpp
Non-modifying Sequence Algorithms
In find(In first, In last, const T& val)
find the first occurence of val in the sequence
In find_if(In first, In last, Pred p) find the first element satisfying p
I1 find_first_of(I1 f1, I2 l1, I2 f2, I2 l2) find the first match between two sequences.
I1 search( I1 f1, I1 l1, I2 f1, I2 l2 )search for the sequence f2...l2 inside f1..l1
Sorted Sequence Algorithms
sort(In first, In last[, class cmp])
find the first occurence of val in the sequence In lower_bound(In first, In last, T const & val[, class cmp]) find the first element not less than val
bool binary_search(In first, In last, T const & val[, class cmp]) check if val appears in the sequence
Out merge( I1 f1, I1 l1, I2 f1, I2 l2, Out out )merge two sorted sequences and write the merged sequence onto the output iterator out