. STL: C++ Standard Library (continued). STL Iterators u Iterators are allow to traverse sequences u...

29
. STL: C++ Standard Library (continued)

Transcript of . STL: C++ Standard Library (continued). STL Iterators u Iterators are allow to traverse sequences u...

.

STL: C++ Standard Library(continued)

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

Ex8: Huffman Code Very easy !! Compression of text files, implement using STL:

Priority queue Map Vector/deque Function objects Copy (algorithm) The more STL you’ll use the more you’ll learn.