Algorithms and Data Structures in C++ PDF
Algorithms and Data Structures in C++ PDF
Weeks 7&8 !
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."
1 !
Weeks 7&8 !
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!
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)) "
2 !
Weeks 7&8 !
3 !
Weeks 7&8 !
Complexity: example 1!
!! What is the O, ! and " complexity of the following code?# double x; std::cin >> x; std::cout << std::sqrt(x);
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;
4 !
Weeks 7&8 !
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; }
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; }
5 !
Weeks 7&8 !
!! The complexity is O(N), but lets 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"
6 !
Weeks 7&8 !
allocators!
allocator! your allocator!
data sequences!
! ! containers! ! list, vector, deque! ! map, set, ! ! your container! builtin arrays,! iostreams,! your data structure!
function objects!
negate, plus, multiplies, ! your function! ! ! predicates! ! less, greater, equal_to, ! ! your predicate!
sequence algorithms!
accumulate, inner_product,! nd, reverse, ! sort, merge, ! your algorithm!
container adapters!
stack, queue, priority_queue!
7 !
Weeks 7&8 !
!! Since this is not very important for numerical simulations I will not go into details. Please read your C++ book"
8 !
Weeks 7&8 !
!! Trees"
!! map !! set !! multimap !! multiset
!! Advantages"
!!Fast O(1) access to arbitrary elements: a[i] is *(a+i)" !!Prots 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)"
9 !
Weeks 7&8 !
!! Removing an element"
!!Also need to copy O(N) elements" a! b! c! d ! a! b! c! e! f! g! h!
e! f! g! h!
a! b! c! d ! a! b! c! d !
e! f! e!
spare ! elements!
a! b! c! d ! a! b! c! d ! e! e! f! e! f! g!
a! b! c! d ! a! b! c! d !
10 !
Weeks 7&8 !
!! In addition to the array operations also the insertion and removal at beginning is O(1)! !! Is needed to implement queues"
!! Allows in O(1)"
!!Pushing an element to the top of the stack" !!Accessing the top-most element" !!Removing the top-most element"
in!
out!
11 !
Weeks 7&8 !
!! Allows in O(1)"
!!Pushing an element to the end of the queue" !!Accessing the rst and last element" in! !!Removing the rst element"
out!
!! There are a number of possible implementations, look at a data structure book for details"
12 !
Weeks 7&8 !
!! Advantages"
!!Fast O(1) insertion and removal anywhere"
!!Just reconnect the pointers"
!! Disadvantage"
!!Does not prot from cache effects" !!Access to an arbitrary element is O(N)" !!Searching in a list is O(N)"
!! A list needs"
!!O(1) operations for arbitrary insertions and removals" !!O(N) operations for random access and searches"
13 !
Weeks 7&8 !
m! 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!
14 !
Weeks 7&8 !
Unbalanced trees!
!! Trees can become unbalanced"
!!Height is no longer O(ln N) but O(N)" !!All operations become O(N)" a! b! c! d! e!
!! Solutions"
!!Rebalance the tree" !!Use self-balancing trees"
f! g! h!
!! But be aware that computer scientists know a large number of other types of trees and data structures"
!!Read the books" !!Ask the experts"
15 !
Weeks 7&8 !
!! 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 once again that assignment and copy have to produce identical copy: in the Penna model the copy constructor should not mutate!"
nd( s, x ) :=" !pos " start of s" "while pos not at end of s" " "if element at pos in s == x! " " "return pos! ! !pos " next position! "return pos" " " int nd( char const(&s)[4], char x )" {" int pos = 0;" while (pos != sizeof(s))" {" if ( s[pos] == x )" return pos;" ++pos;" }" return pos;" }"
struct node" {" "char value;" "node* next;" };" " " " node* nd( node* const s, char x )" {" "node* pos = s;" "while (pos != 0)" "{" " "if ( pos->value == x )" " " "return pos;! ! !pos = pos->next;! "}" "return pos;" }"
16 !
Weeks 7&8 !
nd( s, x ) :=" !pos " start of s" "while pos not at end of s" " "if element at pos in s == x! " " "return pos! ! !pos " next position! "return pos" " char* nd(char const(&s)[4], char x)" {" "char* pos = s;" "while (pos != s + sizeof(s))" "{" " "if ( *pos == x )" " " "return pos;" " "++pos;" "}" "return pos;" }"
struct node" {" "char value;" "node* next;" };" " " " node* nd( node* const s, char x )" {" "node* pos = s;" "while (pos != 0)" "{" " "if ( pos->value == x )" " " "return pos;! ! !pos = pos->next;! "}" "return pos;" }"
nd( s, x ) :=" !pos " start of s" "while pos not at end of s" " "if element at pos in s == x! " " "return pos! ! !pos " next position! "return pos" " char* nd(char const(&s)[4], char x)" {" "char* pos = s;" "while (pos != s + sizeof(s))" "{" " "if ( *pos == x )" " " "return pos;" " "++pos;" "}" "return pos;" }"
struct node" {" "char value;" "node* next;" };" " " " node* nd( node* const s, char x )" {" "node* pos = s;" "while (pos != 0)" "{" " "if ( pos->value == x )" " " "return pos;! ! !pos = pos->next;! "}" "return pos;" }"
17 !
Weeks 7&8 !
NxM Algorithm Implementations?! 1.! 2.! 3.! 4.! nd" copy" merge" transform"
N. "accumulate"
M. "foobar"
"
F. T. S. E.!
Fundamental Theorem of Software Engineering " ""We can solve any problem by introducing an extra level of indirection"! !! ! ! !--Butler Lampson! !"
Andrew Koenig
18 !
Weeks 7&8 !
template <class Iter, class T>! Iter nd( Iter start, Iter nish, T x )! {! Iter pos = start;! for (; pos != end; ++pos)! {! if ( *pos == x )! return pos;! }! return pos;! }!
struct node_iterator! {! // ...! char& operator*() const! { return n->value; }! ! node_iterator& operator++()! { n = n->next; return *this; }! private:! node* n;! };!
template <class Iter, class T>" Iter nd(Iter start, Iter nish, T x)" {" "Iter pos = start;" "for (; pos != nish; ++pos)" "{" " "if ( *pos == x )" " " "return pos;! "}" "return pos;" }"
!! Concept Name?" !! Valid expressions? " !! Preconditions?" !! Postconditions? " !! Complexity guarantees? " !! Associated types?"
19 !
Weeks 7&8 !
Generic traversal !
!! Can we traverse a vector and a list in the same way?" !! Instead of"
for (T* p = a; p !=a+size; ++p) cout << *p;
!! Instead of"
for (node<T>* p=l.first; p!=0; p=p->next) cout << p->value;
!! We want to write"
for (iterator p = a.begin(); p !=a.end(); ++p) cout << *p;
!! We want to write"
for (iterator p = l.begin(); p !=l.end(); ++p) cout << *p;
20 !
Weeks 7&8 !
!! Instead of#
for (T* p = a.p_; p !=a.p_+a.sz_; ++p) cout << *p;
node_iterator<T>& operator++() { p=p->next;} T* operator ->() { return &(p->value);} T& operator*() { return p->value;} bool operator!=(const node_iterator<T>& x) { return p!=x.p;} // more operators missing };
21 !
Weeks 7&8 !
Iterators!
!! have the same functionality as pointers# " !! including pointer arithmetic!"
!!iterator a,b; cout << b-a; // # of elements in [a,b[# "
Container requirements!
!! There are a number of requirements on a container that we will now discuss based on the handouts"
22 !
Weeks 7&8 !
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) rst and last are iterators"
!!container with elements from the range [rst,last["
!! Example:"
!!std::list<double> l; // ll the list // copy list to a vector std::vector<double> v(l.begin(),l.end());
23 !
Weeks 7&8 !
24 !
Weeks 7&8 !
!! 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 [rst,last["
25 !
Weeks 7&8 !
!! for numeric operations are dened:# # 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"
!! 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()"
26 !
Weeks 7&8 !
!!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);"
27 !
Weeks 7&8 !
!! set"
!!unordered container, each entry occurs only once"
!! multiset"
!!unordered container, multiple entries possible# "
!! 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 rst element with key >= k." !!a.upper_bound(k) returns an iterator pointing to the rst 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))" "
28 !
Weeks 7&8 !
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!"
29 !
Weeks 7&8 !
!! Very useful# " !! Are an excellent example in generic programming# " !! We will use them now for the Penna model# Thats why we did not ask you to code the Population class for the Penna model yet!"
Example: find !!
!! A generic function to nd 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;
30 !
Weeks 7&8 !
Example: find_if
31 !
Weeks 7&8 !
!! Solution 2: elegant"
!!copy(v.begin(),v.end(),back_inserter(w)); // uses push_back"
Penna Population!
!! easiest modeled as "
!! class Population : public list<Animal> {}"
!! Removing dead:"
!! remove_if(mem_fun_ref(&Animal::is_dead));"
32 !
Weeks 7&8 !
!! The search range is halved in every step and we thus need at most O(ln N) steps!
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-rst 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; }
33 !
Weeks 7&8 !
Algorithms overview!
!! Nonmodifying"
!! for_each !! find, find_if, find_first_of !! adjacent_find !! count, count_if !! mismatch !! equal !! search !! find_end !! search_n
!! Modifying"
!! transform !! copy, copy_backward !! swap, iter_swap, swap_ranges !! replace, replace_if, replace_copy, replace_copy_if !! fill, fill_n !! generate, generate_n !! remove, remove_if, remove_copy, remove_copy_if !! unique, unique_copy !! reverse, reverse_copy !! rotate, rotate_copy !! random_shuffle"
!! Set Algorithms"
!! includes !! set_union !! set_intersection !! set_difference !! set_symmetric_difference "
!! Permutations"
!! next_permutation !! prev_permutation
34 !
Weeks 7&8 !
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!# "
!! Read Penna's papers and simulate the Atlantic cod! # Physica A, 215, 298 (1995)"
35 !
Weeks 7&8 !
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"
36 !