Выбрать главу

Each of the "remove" forms moves through the range [first, last), finding values that match a removal criterion and copying the unremoved elements over the removed elements (thus effectively removing them). The original order of the unremoved elements is maintained. The return value is an iterator pointing past the end of the range that contains none of the removed elements. The values that this iterator points to are unspecified.

The "if" versions pass each element to pred( ) to determine whether it should be removed. (If pred( ) returns true, the element is removed.) The "copy" versions do not modify the original sequence, but instead copy the unremoved values into a range beginning at result and return an iterator indicating the past-the-end value of this new range.

ForwardIterator unique(ForwardIterator first, ForwardIterator last); ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred); OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result); OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result,  BinaryPredicate binary_pred);

Each of the "unique" functions moves through the range [first, last), finding adjacent values that are equivalent (that is, duplicates) and "removing" the duplicate elements by copying over them. The original order of the unremoved elements is maintained. The return value is an iterator pointing past the end of the range that has the adjacent duplicates removed.

Because only duplicates that are adjacent are removed, it’s likely that you’ll want to call sort( ) before calling a "unique" algorithm, since that will guarantee that all the duplicates are removed.

For each iterator value i in the input range, the versions containing binary_pred calclass="underline" .

binary_pred(*i, *(i-1));

and if the result is true, *i is considered a duplicate.

The "copy" versions do not modify the original sequence, but instead copy the unremoved values into a range beginning at result and return an iterator indicating the past-the-end value of this new range.

Example

This example gives a visual demonstration of the way the "remove" and "unique" functions work.

//: C06:Removing.cpp

// The removing algorithms

#include <algorithm>

#include <cctype>

#include <string>

#include "Generators.h"

#include "PrintSequence.h"

using namespace std;

struct IsUpper {

  bool operator()(char c) {

    return isupper(c);

  }

};

int main() {

  string v;

  v.resize(25);

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

  print(v.begin(), v.end(), "v original", "");

  // Create a set of the characters in v:

  string us(v.begin(), v.end());

  sort(us.begin(), us.end());

  string::iterator it = us.begin(), cit = v.end(),

    uend = unique(us.begin(), us.end());

  // Step through and remove everything:

  while(it != uend) {

    cit = remove(v.begin(), cit, *it);

    print(v.begin(), v.end(), "Complete v", "");

    print(v.begin(), cit, "Pseudo v ", " ");

    cout << "Removed element:\t" << *it

         << "\nPsuedo Last Element:\t"

         << *cit << endl << endl;

    it++;

  }

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

  print(v.begin(), v.end(), "v", "");

  cit = remove_if(v.begin(), v.end(), IsUpper());

  print(v.begin(), cit, "v after remove_if IsUpper", " ");

  // Copying versions are not shown for remove

  // and remove_if.

  sort(v.begin(), cit);

  print(v.begin(), cit, "sorted", " ");

  string v2;

  v2.resize(cit - v.begin());

  unique_copy(v.begin(), cit, v2.begin());

  print(v2.begin(), v2.end(), "unique_copy", " ");

  // Same behavior:

  cit = unique(v.begin(), cit, equal_to<char>());

  print(v.begin(), cit, "unique equal_to<char>", " ");

} ///:~

The string v, which is a container of characters, as you know, is filled with randomly generated characters. Each character is used in a remove statement, but the entire string v is printed out each time so you can see what happens to the rest of the range, after the resulting endpoint (which is stored in cit).

To demonstrate remove_if( ), the address of the standard C library function isupper( ) (in <cctype> is called inside the function object class IsUpper, an object of which is passed as the predicate for remove_if( ). This returns true only if a character is uppercase, so only lowercase characters will remain. Here, the end of the range is used in the call to print( ) so only the remaining elements will appear. The copying versions of remove( ) and remove_if( ) are not shown because they are a simple variation on the noncopying versions, which you should be able to use without an example.

The range of lowercase letters is sorted in preparation for testing the "unique" functions. (The "unique" functions are not undefined if the range isn’t sorted, but it’s probably not what you want.).. First, unique_copy( ) puts the unique elements into a new vector using the default element comparison, and then the form of unique( ) that takes a predicate is used; the predicate used is the built-in function object equal_to( ), which produces the same results as the default element comparison.

Sorting and operations on sorted ranges

A significant category of STL algorithms requires that the range they operate on be in sorted order.

STL provides a number of separate sorting algorithms, depending on whether the sort should be stable, partial, or just regular (non-stable). Oddly enough, only the partial sort has a copying version; otherwise you’ll need to make your own copy before sorting if that’s what you want.

Once your sequence is sorted, you can perform many operations on that sequence, from simply locating an element or group of elements to merging with another sorted sequence or manipulating sequences as mathematical sets.

Each algorithm involved with sorting or operations on sorted sequences has two versions. The first uses the object’s own operator< to perform the comparison, and the second uses operator( )(a, b) to determine the relative order of a and b. Other than this, there are no differences, so this distinction will not be pointed out in the description of each algorithm.