STL算法之常用算法

算法 功能
copy 将一个范围中的元素拷贝到新的地方,并返回目的位置的尾迭代器。
copy_backward 从后往前复制。
fill 用指定值填充范围。
fill_n 用n个指定值填充。
generate 用一个函数的执行结果 填充指定范围 。
generate_n 用一个函数的n次执行结果 填充指定范围。
iter_swap 交换迭代器指向的元素。
move 获得右值引用。
remove/replace 移除/替换 等于给定值的元素。
unique 对于范围内的连续等值元素 只保留一份。
shuffle 打乱指定范围内的元素顺序。


1 copy


函数原型:

template <class InputIterator, class OutputIterator>
  OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);
  • 从前往后 复制。

  • 返回值:返回最后一个被复制的元素的迭代器 + 1。

  • 整个copy过程将调用 assignment operator。

    函数等价于:

template
  OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
  while (first!=last) {
    *result = *first;  // *first 复制到 *result 处。
    ++result; ++first; // *result 已初始化, 所以调用的将是 赋值运算符。
  }
  return result;
}

需要注意的事项:

  • 有解引用操作的迭代器需要保证在 begin() + size() - 1 范围内。否则,越界访问,将触发assert。

    例如:

    vector<int> iv(3); //调用int的“默认构造函数”初始化iv, 而且 iv.size() == 3
    
    auto it = iv.end(); 
    
    int val = *it ; // 这个很明显,此时的it相当于下标3,动态数组 iv[3] 越界。
    
    auto it2 = iv.begin() + 3; 
    int val2 = *it2; // 同理,这个也造成越界

    当出现越界访问时,将触发以下断言(assert):

    vector iterator + offset out of range
    
  • 复制的目的地需要已经初始化。也就是在调用copy的过程中,不会调用对象的构造函数。 这也是与 uninitialized_copy 的主要区别。

  • copy 是依次调用重载的运算符=,uninitialized_copy 是依次调用拷贝构造函数。如果目标区间是未初始化的,应该用uninitialized_copy, 否则用copy。


2 copy_backward


函数原型:

template <class BidirectionalIterator1, class BidirectionalIterator2>
  BidirectionalIterator2 copy_backward (BidirectionalIterator1 first,
                                        BidirectionalIterator1 last,
                                        BidirectionalIterator2 result);
  • 从后往前复制。

  • 跟 copy 相比,以相反的方向进行copy操作。

  • copy 过程同样将调用 assignment operator。

    函数等价于:

template<class BidirectionalIterator1, class BidirectionalIterator2>
  BidirectionalIterator2 copy_backward ( BidirectionalIterator1 first,
                                         BidirectionalIterator1 last,
                                         BidirectionalIterator2 result )
{
  while (last!=first) 
     *(--result) = *(--last);
  return result;
}

示例 1

#include      // std::cout
#include     // std::copy_backward
#include        // std::vector

int main () {
  std::vector<int> myvector;

  // set some values:
  for (int i=1; i<=5; i++)
    myvector.push_back(i*10);          // myvector: 10 20 30 40 50

  myvector.resize(myvector.size()+3);  // allocate space for 3 more elements

  std::copy_backward ( myvector.begin(), myvector.begin()+5, myvector.end() );

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;           // 10 20 30 10 20 30 40 50
  std::cout << '\n'; 

  return 0;
}


3 fill


函数原型:

template <class ForwardIterator, class T>
  void fill(ForwardIterator first, ForwardIterator last, const T& val);
  • 用 val 填充范围 [ first,last )。

    函数等价于:

template <class ForwardIterator, class T>
  void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
  while (first != last) {
    *first = val;
    ++first;
  }
}


4 fill_n


函数原型:

template <class OutputIterator, class Size, class T>
    void fill_n (OutputIterator first, Size n, const T& val);
  • 用 n 个 val 填充范围。


5 generate


函数原型:

template <class ForwardIterator, class Generator>
    void generate (ForwardIterator first,
​        ForwardIterator last, Generator gen);
  • 将一个函数的执行结果保存到指定范围之中。函数执行次数是 last - first 次。

    函数等价于:

template <class ForwardIterator, class Generator>
  void generate ( ForwardIterator first, ForwardIterator last, Generator gen )
{
  while (first != last) {
    *first = gen();
    ++first;
  }
}


6 generate_n


函数原型:

template <class OutputIterator, class Size, class Generator>
  void generate_n (OutputIterator first, Size n, Generator gen);
  • 将函数gen执行n次,结果依次保存到first起始地容器中。

示例2 :

#include      // std::cout
#include     // std::generate_n

int current = 0;
int UniqueNumber () { return ++current; }

int main () {
  int myarray[9];

  std::generate_n (myarray, 9, UniqueNumber);

  std::cout << "myarray contains:";
  for (int i=0; i<9; ++i)
    std::cout << ' ' << myarray[i];
  std::cout << '\n';

  return 0;
}


7 iter_swap


函数原型:

template <class ForwardIterator1,class ForwardIterator2>
    void iter_swap (ForwardIterator1 a,ForwardIterator2 b);
  • 交换迭代器指向的元素的值。

函数等价于:

template <class ForwardIterator1, class ForwardIterator2>
  void iter_swap (ForwardIterator1 a, ForwardIterator2 b)
{
  swap (*a, *b);
}


8 move(c++11)


函数原型:

template <class T>
typename remove_reference<T>::type&& move (T&& arg) noexcept;
  • 获得左值和临时变量 的右值引用。

    函数等价于:

static_castdecltype(arg)>::type&&>(arg);

示例3 :

#include       // std::move
#include      // std::cout
#include        // std::vector
#include        // std::string

int main () {
  std::string foo = "foo-string";
  std::string bar = "bar-string";
  std::vector<std::string> myvector;

  myvector.push_back (foo);                    // copies
  myvector.push_back (std::move(bar));         // moves

  std::cout << "myvector contains:";
  for (std::string& x:myvector) std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}


9 remove/replace


函数原型:

template <class ForwardIterator, class T>
    ForwardIterator remove (ForwardIterator first,ForwardIterator last, const T& val);

template <class ForwardIterator, class T>
    void replace (ForwardIterator first,ForwardIterator last,const T& old_value, ​const T& new_value);
  • 移除/替换 等于给定值的元素。


10 unique


函数原型:

template <class ForwardIterator>
    ForwardIterator unique (ForwardIterator first,ForwardIterator last);

template <class ForwardIterator,
    class BinaryPredicate>
    ForwardIterator unique (ForwardIterator first,ForwardIterator last,BinaryPredicate pred);
  • 对于范围内的连续等值元素 只保留一份。

    函数等价于:

template 
  ForwardIterator unique (ForwardIterator first, ForwardIterator last)
{
  if (first==last) return last;

  ForwardIterator result = first;
  while (++first != last)
  {
    if (!(*result == *first))  // or: if (!pred(*result,*first)) for version (2)
      *(++result)=*first;
  }
  return ++result;
}

示例4 :

#include      // std::cout
#include     // std::unique, std::distance
#include        // std::vector

bool myfunction (int i, int j) {
  return (i==j);
}

int main () {
  int myints[] = {10,20,20,20,30,30,20,20,10};           // 10 20 20 20 30 30 20 20 10
  std::vector<int> myvector (myints,myints+9);

  // using default comparison:
  std::vector<int>::iterator it;
  it = std::unique (myvector.begin(), myvector.end());   // 10 20 30 20 10 ?  ?  ?  ?
                                                         //                ^

  myvector.resize( std::distance(myvector.begin(),it) ); // 10 20 30 20 10

  // using predicate comparison:
  std::unique (myvector.begin(), myvector.end(), myfunction);   // (no changes)

  // print out content:
  std::cout << "myvector contains:";
  for (it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}


11 shuffle


函数原型:

template <class RandomAccessIterator, class URNG>
    void shuffle (RandomAccessIterator first,
        ​RandomAccessIterator last, URNG&& g);
  • 使用指定的随机数引擎打乱指定范围内的元素位置。

    函数等价于:

template<class _RanIt,
    class _Fn1,
    class _Diff> inline
    void _Random_shuffle(_RanIt _First, _RanIt _Last, _Fn1& _Func, _Diff *)
    {    // shuffle nonempty [_First, _Last) using random function _Func
        _RanIt _Next = _First;
        for (_Diff _Index = 2; ++_Next != _Last; ++_Index)
        {    // randomly swap element with self or earlier element
            _Diff _Off = _Func(_Index);
            _STD iter_swap(_Next, _First + _Off);
        }
    }

示例5 :

#include      // std::cout
#include     // std::shuffle
#include         // std::array
#include        // std::default_random_engine
#include        // std::chrono::system_clock

int main () {
  std::array<int,5> foo {1,2,3,4,5};

  // obtain a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();

  shuffle (foo.begin(), foo.end(), std::default_random_engine(seed));

  std::cout << "shuffled elements:";
  for (int& x: foo) std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}

你可能感兴趣的:(C/C++)