View
218
Download
0
Tags:
Embed Size (px)
Citation preview
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_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?'