Data structures and algorithms in the C++ Weeks 7&8
standard library
Algorithms and Data Structures in C++
Algorithms and Data Structures
♦ A key to successful programming
♦ A core subject of computer science taking a full semester
♦ Just teaching the C++ standard library also takes a full semester
♦ Very important for CSE (RW) but there is no special course
♦ I will spend a few weeks on algorithms and data structures in C++
♦ Read a book to learn more, e.g.:
Adam Drozdek “Data Structures and Algorithms in C++” (Brooks/Cole,
2001)
♦ Read a C++ text book (Stroustrup, Lipman) to learn the details of data
structures and algorithms
♦ Use and practice data structures and algorithms in the Penna model
Programming techniques for scientific
simulations
1
Data structures and algorithms in the C++ Weeks 7&8
standard library
Complexity analysis
♦ Answers the question “How does the time needed for an algorithm
scale with the problem size N?”
♦ Worst case analysis: maximum time needed over all possible inputs
♦ Best case analysis: minimum time needed
♦ Average case analysis: average time needed
♦ Amortized analysis: average over a sequence of operations
♦ Usually only worst-case information is given since average case is
much harder to estimate.
The O notation
♦ Is used for worst case analysis:
An algorithm is O(f (N)) if there are constants c and N0, such that for
N≥ N0 the time to perform the algorithm for an input size N is
bounded by t(N) < c f(N)
♦ Consequences
♦ O(f(N)) is identically the same as O(a f(N))
♦ O(a Nx + b Ny) is identically the same as O(Nmax(x,y))
♦ O(Nx) implies O(Ny) for all y ≥ x
Programming techniques for scientific
simulations
2
Data structures and algorithms in the C++ Weeks 7&8
standard library
The Ω and Θ notations
♦ Ω is used for best case analysis:
An algorithm is Ω(f (N)) if there are constants c and N0, such that
for N≥ N0 the time to perform the algorithm for an input size N is
bounded by t(N) > c f(N)
♦ Θ is used if worst and best case scale the same
An algorithm is Θ(f (N)) if it is Ω(f (N)) and O(f (N))
Time assuming 1 billion operations per second
Complexity
N=10
102
103
104
105
106
1
1 ns
1 ns
1 ns
1 ns
1 ns
1ns
ln N
3 ns
7 ns
10 ns
13 ns
17 ns
20 ns
N
10 ns
100 ns
1 µs
10 µs
100 µs
1 ms
N log N
33 ns
664 ns
10 µs
133 µs
1.7 ms
20 ms
N2
100 ns
10 µs
1 ms
100 ms
10 s
17 min
N3
1 µs
1 ms
1 s
17 min
11.5 d
31 a
2N
1 µs
1014 a
10285 a
102996 a
1030086 a
10301013 a
Programming techniques for scientific
simulations
3
Data structures and algorithms in the C++ Weeks 7&8
standard library
Which algorithm do you prefer?
♦ When do you pick algorithm A, when algorithm B? The complexities are
listed below
Algorithm A
Algorithm B
Which do you pick?
O(ln N)
O(N)
O(ln N)
N
O(ln N)
1000 N
ln N
O(N)
1000 ln N
O(N)
ln N
N
ln N
1000 N
1000 ln N
N
Complexity: example 1
♦ What is the O, Ω and Θ complexity of the following code?
double x;
std::cin >> x;
std::cout << std::sqrt(x);
Programming techniques for scientific
simulations
4
Data structures and algorithms in the C++ Weeks 7&8
standard library
Complexity: example 2
♦ What is the O, Ω and Θ complexity of the following code?
unsigned int n;
std::cin >> n;
for (int i=0; i<n; ++i)
std::cout << i*i << “\n”;
Complexity: example 3
♦ What is the O, Ω and Θ complexity of the following code?
unsigned int n;
std::cin >> n;
for (int i=0; i<n; ++i) {
unsigned int sum=0;
for (int j=0; j<i; ++j)
sum += j;
std::cout << sum << “\n”;
}
Programming techniques for scientific
simulations
5
Data structures and algorithms in the C++ Weeks 7&8
standard library
Complexity: example 4
♦ What is the O, Ω and Θ complexity of the following two segments?
♦ Part 1:
unsigned int n;
std::cin >> n;
double* x=new double[n]; // allocate array of n numbers
for (int i=0; i<n; ++i)
std::cin >> x[i];
♦ Part 2:
double y;
std::cin >> y;
for (int i=0; i<n; ++i)
if (x[i]==y) {
std::cout << i << “\n”;
break;
}
Complexity: adding to an array (simple way)
♦ What is the complexity of adding an element to the end of an
array?
♦ allocate a new array with N+1 entries
♦ copy N old entries
♦ delete old arrray
♦ write (N+1)-st element
♦ The complexity is O(N)
Programming techniques for scientific
simulations
6
Data structures and algorithms in the C++ Weeks 7&8
standard library
Complexity: adding to an array (clever way)
♦ What is the complexity of adding an element to the end of an
array?
♦ allocate a new array with 2N entries, but mark only N+1 as used
♦ copy N old entries
♦ delete old arrray
♦ write (N+1)-st element
♦ The complexity is O(N), but letʼs look at the next elements added:
♦ mark one more element as used
♦ write additional element
♦ The complexity here is O(1)
♦ The amortized (averaged) complexity for N elements added is
1
(O(N) + (N −1)O(1)) = O(1)
N
The standard C++ library
♦ consists of several parts
♦ standard C library, same as in C
♦ string class
♦ I/O streams
♦ numeric classes
♦ complex
♦ numeric_limits
♦ valarray
♦ …
♦ former STL (“standard template library”)
♦ Containers (data structures) and algorithms
♦ iterators
♦ generic algorithms
♦ Many other useful classes
Programming techniques for scientific
simulations
7
Data structures and algorithms in the C++ Weeks 7&8
standard library
The string and wstring classes
♦ are very useful class to manipulate strings
♦ string for standard ASCII strings (e.g. “English”)
♦ wstring for wide character strings (e.g. “日本語”)
♦ Contains many useful functions for string manipulation
♦ Adding strings
♦ Counting and searching of characters
♦ Finding substrings
♦ Erasing substrings
♦ …
♦ Since this is not very important for numerical simulations I will not
go into details. Please read your C++ book
The pair template
♦ template <class T1, class T2> class pair {
public:
T1 first;
T2 second;
pair(const T1& f, const T2& s)
: first(f), second(s)
{}
};
♦ will be useful in a number of places
Programming techniques for scientific
simulations
8
Data structures and algorithms in the C++ Weeks 7&8
standard library
Data structures in C++
♦ We will discuss a number of data structures and their implementation
in C++:
♦ Arrays:
♦ Trees
♦ C array
♦ map
♦ vector
♦ set
♦ valarray
♦ multimap
♦ deque
♦ multiset
♦ Linked lists:
♦ Queues and stacks
♦ list
♦ queue
♦ priority_queue
♦ stack
The array or vector data structure
♦ An array/vector is a consecutive range in memory
♦ Advantages
♦ Fast O(1) access to arbitrary elements: a[i] is *(a+i)
♦ Profits from cache effects
♦ Insertion or removal at the end is O(1)
♦ Searching in a sorted array is O(ln N)
♦ Disadvantage
♦ Insertion and removal at arbitrary positions is O(N)
Programming techniques for scientific
simulations
9
Data structures and algorithms in the C++ Weeks 7&8
standard library
Slow O(N) insertion and removal in an array
♦ Inserting an element
♦ Need to copy O(N) elements
a
b
c
d
e
f
g
h
a
b
c
d
x
e
f
g
h
♦ Removing an element
♦ Also need to copy O(N) elements
a
b
c
d
e
f
g
h
a
b
c
e
f
g
h
Fast O(1) removal and insertion at the end of an array
♦ Removing the last element
♦ Just change the size
♦ Capacity 8, size 6:
a
b
c
d
e
f
spare
elements
♦ Capacity 8, size 5:
a
b
c
d
e
♦ Inserting elements at the end
♦ Is amortized O(1)
♦ first double the size and copy in O(N):
a
b
c
d
a
b
c
d
e
♦ then just change the size:
a
b
c
d
e
f
a
b
c
d
e
f
g
Programming techniques for scientific
simulations
10
Data structures and algorithms in the C++ Weeks 7&8
standard library
The deque data structure (double ended queue)
♦ Is a variant of an array, more complicated to implement
♦ See a data structures book for details
♦ In addition to the array operations also the insertion and removal at
beginning is O(1)
♦ Is needed to implement queues
The stack data structure
♦ Is like a pile of books
♦ LIFO (last in first out): the last one in is the first one out
♦ Allows in O(1)
♦ Pushing an element to the top of the stack
♦ Accessing the top-most element
in
out
♦ Removing the top-most element
Programming techniques for scientific
simulations
11
Data structures and algorithms in the C++ Weeks 7&8
standard library
The queue data structure
♦ Is like a queue in the Mensa
♦ FIFO (first in first out): the first one in is the first one out
♦ Allows in O(1)
♦ Pushing an element to the end of the queue
♦ Accessing the first and last element
in
♦ Removing the first element
out
The priority queue data structure
♦ Is like a queue in the Mensa, but professors are allowed to go to
the head of the queue (not passing other professors though)
♦ The element with highest priority (as given by the < relation) is the first
one out
♦ If there are elements with equal priority, the first one in the queue is
the first one out
♦ There are a number of possible implementations, look at a data
structure book for details
Programming techniques for scientific
simulations
12
Data structures and algorithms in the C++ Weeks 7&8
standard library
The linked list data structure
♦ An linked list is a collection of objects linked by pointers into a one
-dimensional sequence
head
tail
♦ Advantages
♦ Fast O(1) insertion and removal anywhere
♦ Just reconnect the pointers
♦ Disadvantage
♦ Does not profit from cache effects
♦ Access to an arbitrary element is O(N)
♦ Searching in a list is O(N)
The tree data structures
♦ An array needs
♦ O(N) operations for arbitrary insertions and removals
♦ O(1) operations for random access
♦ O(N) operations for searches
♦ O(ln N) operations for searches in a sorted array
♦ A list needs
♦ O(1) operations for arbitrary insertions and removals
♦ O(N) operations for random access and searches
♦ What if both need to be fast? Use a tree data structure:
♦ O(ln N) operations for arbitrary insertions and removals
♦ O(ln N) operations for random access and searches
Programming techniques for scientific
simulations
13
Data structures and algorithms in the C++ Weeks 7&8
standard library
A node in a binary tree
♦ Each node is always linked to two child nodes
♦ The left child is always smaller
♦ The right child node is always larger
d
s
A binary tree
♦ Can store N=2n-1 nodes in a tree of height n
♦ Any access needs at most n = O(ln N) steps
♦ Example: a tree of height 5 with 12 nodes
root
m
branch
d
s
b
g
n
x
a
i
w
y
z
leaf
Programming techniques for scientific
simulations
14
Data structures and algorithms in the C++ Weeks 7&8
standard library
Unbalanced trees
♦ Trees can become unbalanced
a
♦ Height is no longer O(ln N) but O(N)
♦ All operations become O(N)
b
c
♦ Solutions
♦ Rebalance the tree
d
♦ Use self-balancing trees
e
♦ Look into a data structures book to learn more
f
Tree data structures in the C++ standard
♦ Fortunately the C++ standard contains a number of self-balancing
tree data structures suitable for most purposes:
♦ set
♦ multiset
♦ map
♦ multimap
♦ But be aware that computer scientists know a large number of
other types of trees and data structures
♦ Read the books
♦ Ask the experts
Programming techniques for scientific
simulations
15
Data structures and algorithms in the C++ Weeks 7&8
standard library
The container concept in the C++ standard
♦ Containers are sequences of data, in any of the data structures
♦ vector<T> is an array of elements of type T
♦ list<T> is a doubly linked list of elements of type T
♦ set<T> is a tree of elements of type T
…
♦ The standard assumes the following requirements for the element
T of a container:
♦ default constructor T()
♦ assignment T& operator=(const T&)
♦ copy constructor T(const T&)
♦ Note that assignment and copy have to produce identical copy:
in the Penna model the copy constructor should not mutate!
Traversing an array and a linked list
♦ Two ways for traversing an array
♦ Traversing a linked list
♦ Using an index:
template <class T> struct Node
{
T elem; // the element
T* a = new T[size];
Node<T>* next; // the next Node
for (int n=0;n<size;++n)
};
cout << a[n];
template<class T> struct List
♦ Using pointers:
{
Node<T>* first;
};
for (T* p = a;
List<T> l;
p !=a+size;
…
++p)
for (Node<T>* p=l.first;
cout << *p;
p!=0;
p=p->next)
cout << p->elem;
Programming techniques for scientific
simulations
16
Data structures and algorithms in the C++ Weeks 7&8
standard library
Generic traversal
♦ Can we traverse a vector and a
list in the same way?
♦ Instead of
♦ Instead of
for (T* p = a;
for (Node<T>* p=l.first;
p !=a+size;
p!=0;
++p)
p=p->next)
cout << *p;
cout << p->elem;
♦ We want to write
♦ We want to write
for (iterator p = a.begin();
for (iterator p = l.begin();
p !=a.end();
p !=l.end();
++p)
++p)
cout << *p;
cout << *p;
Implementing iterators for the array
template<class T>
♦ Now allows the desired syntax:
class Array {
public:
typedef T* iterator;
for (Array<T>::iterator p =
typedef unsigned size_type;
a.begin();
Array();
p !=a.end();
Array(size_type);
++p)
cout << *p;
iterator begin()
{ return p_;}
♦ Instead of
iterator end()
{ return p_+sz_;}
for (T* p = a.p_;
private:
p !=a.p_+a.sz_;
T* p_;
++p)
size_type sz_;
cout << *p;
};
Programming techniques for scientific
simulations
17
Data structures and algorithms in the C++ Weeks 7&8
standard library
Implementing iterators for the linked list
template <class T>
template<class T>
struct LI {
class List {
Node<T>* p;
Node<T>* first;
LI(Node<T>* q) :p(q) {}
public:
typedef LI<T> iterator;
LI<T>& operator++()
{ p=p->next;}
iterator begin()
{ return iterator(first);}
T* operator ->()
{ return &(p->elem);}
iterator end()
{ return iterator(0);}
T& operator*()
};
{ return p->elem;}
bool operator!=(const LI& x)
♦ Now also allows the desired syntax:
{ return p!=x.p;}
for (List<T>::iterator p = l.begin();
// more operators missing …
p !=l.end();
};
++p)
cout << *p;
Iterators
♦ have the same functionality as pointers
♦ including pointer arithmetic!
♦ iterator a,b; cout << b-a; // # of elements in [a,b[
♦ exist in several versions
♦ forward iterators … move forward through sequence
♦ backward iterators … move backwards through sequence
♦ bidirectional iterators … can move any direction
♦ input iterators … can be read: x=*p;
♦ output iterators … can be written: *p=x;
♦ and all these in const versions (except output iterators)
Programming techniques for scientific
simulations
18
Data structures and algorithms in the C++ Weeks 7&8
standard library
Container requirements
♦ There are a number of requirements on a container that we will
now discuss based on the handouts
Containers and sequences
♦ A container is a collection of elements in a data structure
♦ A sequence is a container with a linear ordering (not a tree)
♦ vector
♦ deque
♦ list
♦ An associative container is based on a tree, finds element by a key
♦ map
♦ multimap
♦ set
♦ multiset
♦ The properties are defined on the handouts from the standard
♦ A few special points mentioned on the slides
Programming techniques for scientific
simulations
19
Data structures and algorithms in the C++ Weeks 7&8
standard library
Sequence constructors
♦ A sequence is a linear container (vector, deque, list,…)
♦ Constructors
♦ container() … empty container
♦ container(n) … n elements with default value
♦ container(n,x) … n elements with value x
♦ container(c) … copy of container c
♦ container(first,last) … first and last are iterators
♦ container with elements from the range [first,last[
♦ Example:
♦ std::list<double> l;
// fill the list
…
// copy list to a vector
std::vector<double> v(l.begin(),l.end());
Direct element access in deque and vector
♦ Optional element access (not implemented for all containers)
♦ T& container[k] … k-th element, no range check
♦ T& container.at(k) … k-th element, with range check
♦ T& container.front() … first element
♦ T& container.back() … last element
Programming techniques for scientific
simulations
20
Data structures and algorithms in the C++ Weeks 7&8
standard library
Inserting and removing at the beginning and end
♦ For all sequences: inserting/removing at end
♦ container.push_back(T x) // add another element at end
♦ container.pop_back() // remove last element
♦ For list and deque (stack, queue)
♦ container.push_first(T x) // insert element at start
♦ container.pop_first() // remove first element
Inserting and erasing anywhere in a sequence
♦ List operations (slow for vectors, deque etc.!)
♦ insert (p,x) // insert x before p
♦ insert(p,n,x) // insert n copies of x before p
♦ insert(p,first,last) // insert [first,last[ before p
♦ erase(p) // erase element at p
♦ erase(first,last) // erase range[first,last[
♦ clear() // erase all
Programming techniques for scientific
simulations
21
Data structures and algorithms in the C++ Weeks 7&8
standard library
Vector specific operations
♦ Changing the size
♦ void resize(size_type)
♦ void reserve(size_type)
♦ size_type capacity()
♦ Note:
♦ reserve and capacity regard memory allocated for vector!
♦ resize and size regard memory currently used for vector data
♦ Assignments
♦ container = c … copy of container c
♦ container.assign(n) …assign n elements the default value
♦ container.assign(n,x) … assign n elements the value x
♦ container.assign(first,last) … assign values from the range
[first,last[
♦ Watch out: assignment does not allocate, do a resize before!
The valarray template
♦ acts like a vector but with additional (mis)features:
♦ No iterators
♦ No reserve
♦ Resize is fast but erases contents
♦ for numeric operations are defined:
std::valarray<double> x(100), y(100), z(100);
x=y+exp(z);
♦ Be careful: it is not the fastest library!
♦ We will learn about faster libraries later
Programming techniques for scientific
simulations
22
Data structures and algorithms in the C++ Weeks 7&8
standard library
Sequence adapters: queue and stack
♦ are based on deques, but can also use vectors and lists
♦ stack is first in-last out
♦ queue is first in-first out
♦ priority_queue prioritizes with < operator
♦ stack functions
♦ void push(const T& x) … insert at top
♦ void pop() … removes top
♦ T& top()
♦ const T& top() const
♦ queue functions
♦ void push(const T& x) … inserts at end
♦ void pop() … removes front
♦ T& front(), T& back(),
const T& front(), const T& back()
list -specific functions
♦ The following functions exist only for std::list:
♦ splice
♦ joins lists without copying, moves elements from one to end of the other
♦ sort
♦ optimized sort, just relinks the list without copying elements
♦ merge
♦ preserves order when “splicing” sorted lists
♦ remove(T x)
♦ remove_if(criterion)
♦ criterion is a function object or function, returning a bool and taking a const T& as
argument, see Penna model
♦ example:
bool is_negative(const T& x) { return x<0;}
♦ can be used like
list.remove_if(is_negative);
Programming techniques for scientific
simulations
23
Data structures and algorithms in the C++ Weeks 7&8
standard library
The map class
♦ implements associative arrays
♦ map<std::string,long> phone_book;
phone_book[“Troyer”] = 32589;
phone_book[“Heeb”] = 32591;
if(phone_book[name])
cout << “The phone number of “ << name << “ is “
<< phone_book[name];
else
cout << name << “\’s phone number is unknown!’;
♦ is implemented as a tree of pairs
♦ Take care:
♦ map<T1,T2>::value_type is pair<T1,T2>
♦ map<T1,T2>::key_type is T1
♦ map<T1,T2>::mapped_type is T2
♦ insert, remove, … are sometimes at first sight confusing for a map!
Other tree-like containers
♦ multimap
♦ can contain more than one entry (e.g. phone number) per key
♦ set
♦ unordered container, each entry occurs only once
♦ multiset
♦ unordered container, multiple entries possible
♦ extensions are no problem
♦ if a data structure is missing, just write your own
♦ good exercise for understanding of containers
Programming techniques for scientific
simulations
24
Data structures and algorithms in the C++ Weeks 7&8
standard library
Search operations in trees
♦ In a map<K,V>, K is the key type and V the mapped type
♦ Attention: iterators point to pairs
♦ In a map<T>, T is the key type and also the value_type
♦ Fast O(log N) searches are possible in trees:
♦ a.find(k) returns an iterator pointing to an element with key k or
end() if it is not found.
♦ a.count(k) returns the number of elements with key k.
♦ a.lower_bound(k) returns an iterator pointing to the first element
with key >= k.
♦ a.upper_bound(k) returns an iterator pointing to the first element
with key > k.
♦ a.equal_range(k) is equivalent to but faster than
std::make_pair(a.lower_bound(k) , a.upper_bound(k))
Search example in a tree
♦ Look for all my phone numbers:
♦ // some typedefs
typedef multimap<std::string, int> phonebook_t;
typedef phonebook_t::const_iterator IT;
typedef phonebook_t::value_type value_type;
// the phonebook
phonebook_t phonebook;
// fill the phonebook
phonebook.insert(value_type(“Troyer”,32589));
…
// search all my phone numbers
pair< IT,IT> range = phonebook.equal_range(“Troyer”);
// print all my phone numbers
for (IT it=range.first; it != range.second;++it)
cout << it->second << “\n”;
Programming techniques for scientific
simulations
25
Data structures and algorithms in the C++ Weeks 7&8
standard library
Almost Containers
♦ C-style array
♦ string
♦ valarray
♦ bitset
♦ They all provide almost all the functionality of a container
♦ They can be used like a container in many instances, but not all
♦ int x[5] = {3,7,2,9,4};
vector<int> v(x,x+5);
♦ uses vector(first,last), pointers are also iterators!
The generic algorithms
♦ Implement a big number of useful algorithms
♦ Can be used on any container
♦ rely only on existence of iterators
♦ “container-free algorithms”
♦ now all the fuss about containers pays off!
♦ Very useful
♦ Are an excellent example in generic programming
♦ We will use them now for the Penna model
Thatʼs why we did not ask you to code the Population class for the
Penna model yet!
Programming techniques for scientific
simulations
26
Data structures and algorithms in the C++ Weeks 7&8
standard library
Example: find
♦ A generic function to find an element in a container:
♦ list<string> fruits;
list<string>::const_iterator found =
find(fruits.begin(),fruits.end(),”apple”);
if (found==fruits.end()) // end means invalid iterator
cout << “No apple in the list”;
else
cout << “Found it: “ << *found << “\n”;
♦ find declared and implemented as
♦ <template class In, class T>
In find(In first, In last, T v) {
while (first != last && *first != v)
++first;
return first;
}
Example: find_if
♦ takes predicate (function object or function)
♦ bool favorite_fruits(const std::string& name)
{ return (name==“apple” || name == “orange”);}
♦ can be used with find_if function:
♦ list<string>::const_iterator found =
find_if(fruits.begin(),fruits.end(),favorite_fruits);
if (found==fruits.end())
cout << “No favorite fruits in the list”;
else
cout << “Found it: “ << *found << “\n”;
♦ find_if declared and implemented as as
♦ <template class In, class Pred>
In find_if(In first, In last, Pred p) {
while (first != last && !p(*first) )
++first;
return first;
}
Programming techniques for scientific
simulations
27
Data structures and algorithms in the C++ Weeks 7&8
standard library
Member functions as predicates
♦ We want to find the first pregnant animal:
♦ list<Animal> pop;
find_if(pop.begin(),pop.end(),is_pregnant)
♦ This does not work as expected, it expects
♦ bool is_pregnant(const Animal&);
♦ We want to use
♦ bool Animal::pregnant() const
♦ Solution: mem_fun_ref function adapter
♦ find_if(pop.begin(),pop.end(),
mem_fun_ref(&Animal::pregnant));
♦ Many other useful adapters available
♦ Once again: please read the books before coding your own!
push_back and back_inserter
♦ Attention:
♦ vector<int> v,w;
for (int k=0;k<100;++k){
v[k]=k; //error: v is size 0!
w.push_back(k); // OK:grows the array and assigns
}
♦ Same problem with copy:
♦ vector<int> v(100), w(0);
copy(v.begin(),v.end(),w.begin()); // problem: w of size 0!
♦ Solution1: vectors only
♦ w.resize(v.size()); copy(v.begin(),v.end(),w.begin());
♦ Solution 2: elegant
♦ copy(v.begin(),v.end(),back_inserter(w)); // uses push_back
♦ also push_front and front_inserter for some containers
Programming techniques for scientific
simulations
28
Data structures and algorithms in the C++ Weeks 7&8
standard library
Penna Population
♦ easiest modeled as
♦ class Population : public list<Animal> {…}
♦ Removing dead:
♦ remove_if(mem_fun_ref(&Animal::is_dead));
♦ Removing dead, and others with probability N/N0:
♦ remove_if(animal_dies(N/N0));
♦ where animal_dies is a function object taking N/N0 as parameter
♦ Inserting children:
♦ cannot go into same container, as that might invalidate iterators:
vector<Animal> children;
for(const_iterator a=begin();a!=end();++a)
if(a->pregnant())
children.push_back(a->child());
copy(children.begin(),children.end(),
back_inserter(*this);
The binary search
♦ Searching using binary search in a sorted vector is O(ln N)
♦ Binary search is recursive search in range [begin,end[
♦ If range is empty, return
♦ Otherwise test middle=begin+(end-begin)/2
♦ If the element in the middle is the search value, we are done
♦ If it is larger, search in [begin,middle[
♦ If it is smaller, search in [middle,end[
♦ The search range is halved in every step and we thus need at most
O(ln N) steps
Programming techniques for scientific
simulations
29
Data structures and algorithms in the C++ Weeks 7&8
standard library
Example: lower_bound
template<class IT, class T>
IT lower_bound(IT first, IT last, const T& val) {
typedef typename iterator_traits<IT>::difference_type dist_t;
dist_t len = distance(first, last); // generic function for last-first
dist_t half;
IT middle;
while (len > 0) {
half = len >> 1; // faster version of half=len/2
middle = first;
advance(middle, half);// generic function for middle+=half
if (*middle < val) {
first = middle;
++first;
len = len - half - 1;
}
else
len = half;
}
return first;
}
Algorithms overview
♦ Nonmodifying
♦ Modifying
♦ for_each
♦ transform
♦ find, find_if, ♦ copy, copy_backward
find_first_of
♦ swap, iter_swap,
♦ adjacent_find
swap_ranges
♦ count, count_if
♦ replace, replace_if,
♦ mismatch
replace_copy,
♦ equal
replace_copy_if
♦ fill, fill_n
♦ search
♦ generate, generate_n
♦ find_end
♦ remove, remove_if,
♦ search_n
remove_copy,
remove_copy_if
♦ unique, unique_copy
♦ reverse, reverse_copy
♦ rotate, rotate_copy
♦ random_shuffle
Programming techniques for scientific
simulations
30
Data structures and algorithms in the C++ Weeks 7&8
standard library
Algorithms overview (continued)
♦ Sorted Sequences
♦ Set Algorithms
♦ sort,stable_sort
♦ includes
♦ partial_sort, ♦ set_union
partial_sort_copy
♦ set_intersection
♦ nth_element
♦ set_difference
♦ lower_bound, upper_bound
♦ set_symmetric_difference
♦ equal_range
♦ binary_search
♦ Minimum and Maximum
♦ merge, inplace_merge
♦ min
♦ partition, ♦ max
stable_partition
♦ min_element
♦ max_element
♦ Permutations
♦ lexicographical_compare
♦ next_permutation
♦ prev_permutation
Exercise
♦ Code the population class for the Penna model based on a
standard container
♦ Use function objects to determine death
♦ In the example we used a loop.
♦ Can you code the population class without using any loop?
♦ This would increase the reliability as the structure is simpler!
♦ Also add fishing in two variants:
♦ fish some percentage of the whole population
♦ fish some percentage of adults only
♦ Read Penna's papers and simulate the Atlantic cod!
Physica A, 215, 298 (1995)
Programming techniques for scientific
simulations
31
Data structures and algorithms in the C++ Weeks 7&8
standard library
stream iterators and Shakespeare
♦ Iterators can also be used for streams and files
♦ istream_iterator
♦ ostream_iterator
♦ Now you should be able to understand Shakespeare:
int main()
{
vector<string> data;
copy(istream_iterator<string>(cin),istream_iterator<string>(),
back_inserter(data));
sort(data.begin(), data.end());
unique_copy(data.begin(),data.end(),ostream_iterator<string>(cout,"\n"));
}
Summary
♦ Please read the sections on
♦ containers
♦ iterators
♦ algorithms
♦ in Stroustrup or Lippman (3rd editions only!)
♦ Examples of excellent class and function designs
♦ Before writing your own functions and classes:
Check the standard C++ library!
♦ When writing your own functions/classes:
Try to emulate the design of the standard library
♦ Don't forget to include the required headers:
♦ <algorithm>, <functional>, <map>, <iterators>, … as needed
Programming techniques for scientific
simulations
32