mutating algorithms all the algorithms we have seen have not modified the containers some algorithms...

31
Mutating Algorithms • All the algorithms we have seen have not modified the containers • Some algorithms do modify values • They do not modify iterators, only the values they point to • This causes some algorithms to be a little strange

Post on 19-Dec-2015

218 views

Category:

Documents


0 download

TRANSCRIPT

Mutating Algorithms

• All the algorithms we have seen have not modified the containers

• Some algorithms do modify values

• They do not modify iterators, only the values they point to

• This causes some algorithms to be a little strange

copy

Copies element from one range to another Returns an iterator at the end of the second range int main() {char array[] = "1234567890";vector<char> v(array, array+strlen(array));list<char> l1(v.size());list<char> l2;copy(v.begin(),v.end(),l1.begin());copy(v.begin(),v.end(),back_inserter(l2));

}

copy_backward

• Just like copy only does the assignments in the reverse order

int main() {int array[] = { 1,2,3,4,5,6,7,8,9,10};copy_backward(array,array+8,array+10);copy(array,array+10,

ostream_iterator<int>(cout, " "));}

swap_ranges

• Exchanges the contents of two ranges

• Returns an iterator at the end of the second range int main() {

int array[5] = {1,2,3,4,5};

vector<int> v;

for(int i=1;i<=5;i++)

v.push_back(i*10); swap_ranges(v.begin(),v.end(),array);

}

transform

• Like for_each, except copies results to a range

• Returns an iterator at the end of the output range int main() {

int a1[] = {1,2,3,4,5};

int a2[] = {6,7,8,9,10};

transform(a1,a1+5,a2,

ostream_iterator<int>(cout, " "), plus<int>());

}

replace

• Replaces all occurrences of one value with another

• There is also a replace_copy int main() {

int array[] = {1,2,3,4,5,1,2,3,4,5};

replace(array,array+10,3,10);

copy(array,array+10,

ostream_iterator<int>(cout," "));

}

replace_if

• Like replace except uses a predicate instead of a comparison

• There is also a replace_if_copy int main() {

int array[] = {1,2,3,4,5,1,2,3,4,5};

replace(array,array+10,

bind2nd(less<int>(),3),10);

copy(array,array+10,

ostream_iterator<int>(cout," "));

}

fill and fill_n• fill assigns a value to every element of a range

• fill_n assigns a value to n elements starting at an iterator

int main() {

vector<int> v(4); fill(v.begin(),v.end(),42); fill_n(back_inserter(v),4,24); copy(v.begin(),v.end(), ostream_iterator<int>(cout, " "));

}

generate and generate_n

• generate is like fill except it gets values from a function object

• generate_n does what you would expect as well. int main() {

vector<int> v(1000);

generate(v.begin(),v.end(),rand);

generate_n(ostream_iterator<int>(cout,"\n"),

1000, rand);

}

remove• Removes occurances of a value from a range

• Remove has a strange definition though

• The iterators can't be changed, so the length of range is fixed

• Instead a new last iterator is returned

• Anything after the new last iterator has an unspecified value

• To actually delete elements from a sequence you can use:s.erase(remove(s.begin(),s.end(),v),s.end())

int main() {

int a[] = {1,2,1,2,3,1,2,3,1};

const int N = sizeof(a) / sizeof(a[0]);

copy(a,a+N,

ostream_iterator<int>(cout," "));

cout << endl;

remove(a,a+N,1);

copy(a,a+N,

ostream_iterator<int>(cout," "));

cout << endl;

}

remove_if

• Removes elements for which a predicate is true

• Otherwise it behaves like remove

remove_copy

• A mix of remove and copy

• Copies from one range to another

• Doesn't copy the values that match the one to remove

• There is also a remove_copy_if

• Doesn't have the weirdness of remove

unique

• Removes duplicate elements

• Only removes adjacent duplicates

• Has all the strangeness of remove

• Returns a new last since it can't delete elements

• Can pass a BinaryPredicate to use for comparisons

unique example

int main() {

int a[] = {1,1,2,1,2,3,1,1,1,2,3,2,2};

const int N = sizeof(a) / sizeof(a[0]);

unique(a,a+N);

copy(a,a+N,

ostream_iterator<int>(cout," "));

}

reverse

Reverses a range Requires Bidirectional Iterators There is also reverse_copy int main() {string array[] = { "one", "two",

"three" };reverse(array,array+3);cout << array[0];

}

rotate

Swaps the two ranges [first,middle) and [middle,last)

There is also rotate_copy int main() {int array[] = { 1,2,3,4,5,6,7,8,9,10};rotate(array,array+3,array+N);copy(array,array+N,

ostream_iterator<int>(cout," "));}

next_permutation

Transforms a range to be the next permutation of that range

Permutations are ordered lexicographically Returns true if there is a suitable permutation Returns false (and tranforms range to smallest

permutation) if not There is also a prev_permutation

next_permutation example

int main() {int array[] = {1,2,3,4,5};do {

copy(array,array+5, ostream_iterator<int>(cout," "));cout << endl;

} while (next_permutation(array,array+5));}

partition Puts elements satisfying a predicate before

those that don't Does not keep relative order stable_partition is the same but does. int main() {int array[] = {1,2,3,4,5,6,7,8,9,10};partition(array,array+10,

compose1(bind2nd(equal_to<int>,0), bind2nd(modulus<int>,2)));

copy(array,array+10,ostream_iterator<int>(cout," "));

}

random_shuffle

Rearranges the range into a random order All permutations are equally favoured

int main() {string array[] = { "one", "two", "three"};random_shuffle(array,array+3);copy(array,array+3,

ostream_iterator<string>(cout,"\n"));}

random_sample• Randomly copies a sample of a range Is

• almost a random_shuffle_copy

• Unusually copies as many elements as the output range has

• There is also a random_sample_n int main() {int a[] = { 1,2,3,4,5,6,7,8,9,10};int a2[5];random_sample(a, a+10, a2, a2+5);copy(a2,a2+5,

ostream_iterator<int>(cout, " "));}

sort• Sorts a range

• By default sorts into ascending order

• Can be passed a StrictWeakOrdering function object

• stable_sort should be used if stability is required int main() {string array[] = { "one", "two", "three”};sort(array,array+3);copy(array,array+3,

ostream_iterator<string>(cout, " "));}

partial_sort Puts the smallest n elements of a range at the

start in sorted order More efficient than sort if you only need a few

elements There is also a partial_sort_copy which is a little

different int main() {int array[] = {76,2,78,4,6,2,8,2,7,9};partial_sort(array,array+5,array+10);copy(array,array+10,

ostream_iterator<int>(cout," "));}

nth_element Places the value at the nth element that would be there

if the range was sorted Every element before the nth element is less than or

equal to it Every element after the nth element is greater than or

equal to it int main() {int array[] = { 65,23,83,54,29 };nth_element(array,array+2,array+5);copy(array,array+5,

ostream_iterator<int>(cout, " "));}

is_sorted

• Tests if a range is sorted

• Returns the appropriate boolean value int main() {int array[] = {1,5,3,2,4};while (!is_sorted(array,array+5))

random_shuffle(array,array+5);}

binary_search

• Returns true if a value is found in a range

• Only works on sorted ranges

• Is much faster than a linear find

• Doesn't return the appropriate iterator

• Not used often

lower_bound and upper_bound Find the first or last elements in a sorted range

of a value If the value is not found an iterator at a location

where it would be is returned. int main() {int array[] = {1,2,3,4,4,4,4,8,9,9};int *il =

lower_bound(array,array+10,4);int *iu=upper_bound(array,array+10,4);cout << "Four occurs in the range: ”

<< (il-array)<<’-’<<(iu-array) << endl;

}

equal_range Returns the range where an element occurs in a

sorted range Result is a pair of iterators The combination of lower_bound and

upper_bound int main() {int array[] = {1,2,3,4,4,4,4,8,9,9};

pair<int*,int*> r =equal_range(array,array+10,4);

cout << "Four occurs in the range: ” << (r.first-array)<<‘-’ << (r.second-array) << endl;

}

merge

Combines two sorted ranges into a single sorted range

It is stable int main() {int even[] = {0,2,4,6,8,10};int odd[] = {1,3,5,7,9};

merge(odd,odd+5,even,even+6,ostream_iterator<int>(cout, " "));

}

• We have quickly looked at a lot of algorithms

• There are a lot more in the STL

• Using them makes coding much easier, since you have to write less

• For exam purposes what you probably want to know is: I might ask 'You need to do <X> to a <Y> which

algorithms would you use?'

I might ask 'You need to do <Z> which containers would you use?'

I might ask 'What properties does a <Y> have?'