STL algorithm函数总结
algorithm
官方文档
https://www.cplusplus.com/reference/algorithm/
很多函数其实用不到,只有少部分用的很多,其实官方文档写的很清楚也有例子,这里总结一下个人认为比较常用的函数
count
计算给定迭代器区间内与元素相等的个数
int count (InputIterator first, InputIterator last, const T& val);
int myints[] = {10,20,30,30,20,10,10,20}; // 8 elements
int mycount = std::count (myints, myints+8, 10);
std::cout << "10 appears " << mycount << " times.\n";
//10 appears 3 times.
fill
给定迭代器区间使用给定值填充
void fill (ForwardIterator first, ForwardIterator last, const T& val);
generate
以指定动作运算结果填充特定范围内的元素内容,类似python里的列表生成式的作用。第三个参数必须是lambda函数或者函数,或者函数对象,即均有重载operator()()的类对象。
void generate (ForwardIterator first, ForwardIterator last, Generator gen);
官方实例
// generate algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::generate
#include <vector> // std::vector
#include <ctime> // std::time
#include <cstdlib> // std::rand, std::srand
// function generator:
int RandomNumber () { return (std::rand()%100); }
// class generator:
struct c_unique {
int current;
c_unique() {current=0;}
int operator()() {return ++current;}
} UniqueNumber;
int main () {
std::srand ( unsigned ( std::time(0) ) );
std::vector<int> myvector (8);
std::generate (myvector.begin(), myvector.end(), RandomNumber);
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::generate (myvector.begin(), myvector.end(), UniqueNumber);
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
generate_n
与generate类似,不过第二个参数不为迭代器末尾,为生成数量。
void generate_n (OutputIterator first, Size n, Generator gen);
reverse
给定区间反转,是原内存进行反转,没有返回值。
void reverse (BidirectionalIterator first, BidirectionalIterator last);
shuffle
random_shuffle 对给定区间进行随机打乱,可传入自定义随机函数。
shuffle需要传入随机数引擎。
random_shuffle 的定义等效如下。可以看到gen函数应是生成一个在0-i之间的随机数。
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator& gen)
{
iterator_traits<RandomAccessIterator>::difference_type i, n;
n = (last-first);
for (i=n-1; i>0; --i) {
swap (first[i],first[gen(i+1)]);
}
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last);
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last,RandomNumberGenerator&& gen);
void shuffle (RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& g);
实例
// random_shuffle example
#include <iostream> // std::cout
#include <algorithm> // std::random_shuffle
#include <vector> // std::vector
#include <ctime> // std::time
#include <cstdlib> // std::rand, std::srand
// random generator function:
int myrandom (int i) { return std::rand()%i;}
int main () {
std::srand ( unsigned ( std::time(0) ) );
std::vector<int> myvector;
// set some values:
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
// using built-in random generator:
std::random_shuffle ( myvector.begin(), myvector.end() );
// using myrandom:
std::random_shuffle ( myvector.begin(), myvector.end(), myrandom);
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
partition
partition算法作用为对指定范围内元素重新排序,使用输入的函数,把结果为true的元素放在结果为false的元素之前,pred为自定义函数,返回值为正向迭代器,其指向的是两部分数据的分界位置,更确切地说,指向的是第二组数据中的第 1 个元素。
ForwardIterator partition (ForwardIterator first,
ForwardIterator last, UnaryPredicate pred);
实例
#include <iostream> // std::cout
#include <algorithm> // std::partition
#include <vector> // std::vector
bool IsOdd (int i) { return (i%2)==1; }
int main () {
std::vector<int> myvector;
// set some values:
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
std::vector<int>::iterator bound;
bound = std::partition (myvector.begin(), myvector.end(), IsOdd);
// print out content:
std::cout << "odd elements:";
for (std::vector<int>::iterator it=myvector.begin(); it!=bound; ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "even elements:";
for (std::vector<int>::iterator it=bound; it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
sort
对指定区间排序,默认升序,可自定比较函数。同样的三种方式。
// sort algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::sort
#include <vector> // std::vector
bool myfunction(int i, int j) { return (i<j); }
struct myclass {
bool operator() (int i, int j) { return (i<j); }
} myobject;
int main() {
int myints[] = { 32,71,12,45,26,80,53,33 };
std::vector<int> myvector(myints, myints + 8); // 32 71 12 45 26 80 53 33
std::sort(myvector.begin(), myvector.end(), [](const int &a, const int &b) {return a < b; }); // 12 32 45 71(26 33 53 80)
std::cout << "lambda:myvector contains:";
for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
// using function as comp
std::sort(myvector.begin(), myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)
std::cout << "myfunction:myvector contains:";
for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
// using object as comp
std::sort(myvector.begin(), myvector.end(), myobject); //(12 26 32 33 45 53 71 80)
// print out content:
std::cout << "myobject:myvector contains:";
for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
stable_sort
与sort使用方法一致,但会保证前后顺序。
sort是快速排序实现,因此是不稳定的;stable_sort是归并排序实现,因此是稳定的
lower_bound
二分查找非递减序列内第一个大于或等于某个元素的位置。
可自定义比较函数,函数的返回的值指示是否认为第一个参数在第二个参数之前。
ForwardIterator lower_bound (ForwardIterator first,ForwardIterator last, const T& val);
ForwardIterator lower_bound (ForwardIterator first,ForwardIterator last, const T& val, Compare comp);
定义如下:
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = distance(first,last);
while (count>0)
{
it = first; step=count/2; advance (it,step);
if (comp(*it,val)) {
first=++it;
count-=step+1;
}
else count=step;
}
return first;
}
一般默认comp(it,val)为<比较,所以由定义我们看出lower是找出第一个使it和val的比较函数为假的位置。
upper_bound
查找非递减序列内第一个大于某个元素的位置。与lower_bound用法一致。定义如下:
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = std::distance(first,last);
while (count>0)
{
it = first; step=count/2; std::advance (it,step);
if (!comp(val,*it)) {
first=++it;
count-=step+1;
}
else count=step;
}
return first;
}
upper比较复杂,因为这里传入cmp的参数是反顺序的。自行理解吧
merge
归并排序,可自定义比较函数,但自定义比较函数使用时需要归并的两个数组必须按cmp函数已经排好序。
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, InputIterator2 last2,OutputIterator result);
OutputIterator merge (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,OutputIterator result, Compare comp);
// merge algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::merge, std::sort
#include <vector> // std::vector
#include <functional>
bool myfunction(const int &i, const int &j) { return (i>j); }
int main() {
int first[] = { 5,10,15,20,25 };
int second[] = { 50,40,30,20,10 };
std::vector<int> v(10);
std::sort(first, first + 5, myfunction);
std::sort(second, second + 5, myfunction);
std::merge(first, first + 5, second, second + 5, v.begin(), myfunction);
std::cout << "The resulting vector contains:";
for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
inplace_merge
对原数组就地排序,需要传入三个位置分成两个区间,区间归并前需要安装cmp进行排序
void inplace_merge (BidirectionalIterator first,BidirectionalIterator middle,BidirectionalIterator last);
void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,BidirectionalIterator last, Compare comp);
实例
// inplace_merge example
#include <iostream> // std::cout
#include <algorithm> // std::inplace_merge, std::sort, std::copy
#include <vector> // std::vector
int main () {
int first[] = {5,10,15,20,25};
int second[] = {50,40,30,20,10};
std::vector<int> v(10);
std::vector<int>::iterator it;
std::sort (first,first+5);
std::sort (second,second+5);
it=std::copy (first, first+5, v.begin());
std::copy (second,second+5,it);
std::inplace_merge (v.begin(),v.begin()+5,v.end());
std::cout << "The resulting vector contains:";
for (it=v.begin(); it!=v.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
min_element
查找最小元素,返回最小位置迭代器。也可自定义比较函数。
ForwardIterator min_element (ForwardIterator first, ForwardIterator last);
ForwardIterator min_element (ForwardIterator first, ForwardIterator last,Compare comp);
定义:
template <class ForwardIterator>
ForwardIterator min_element ( ForwardIterator first, ForwardIterator last )
{
if (first==last) return last;
ForwardIterator smallest = first;
while (++first!=last)
if (comp(*first,*smallest)) smallest=first;
return smallest;
}
// min_element/max_element example
#include <iostream> // std::cout
#include <algorithm> // std::min_element, std::max_element
bool myfn(int i, int j) { return i<j; }
struct myclass {
bool operator() (int i,int j) { return i<j; }
} myobj;
int main () {
int myints[] = {3,7,2,5,6,4,9};
// using default comparison:
std::cout << "The smallest element is " << *std::min_element(myints,myints+7) << '\n';
std::cout << "The largest element is " << *std::max_element(myints,myints+7) << '\n';
// using function myfn as comp:
std::cout << "The smallest element is " << *std::min_element(myints,myints+7,myfn) << '\n';
std::cout << "The largest element is " << *std::max_element(myints,myints+7,myfn) << '\n';
// using object myobj as comp:
std::cout << "The smallest element is " << *std::min_element(myints,myints+7,myobj) << '\n';
std::cout << "The largest element is " << *std::max_element(myints,myints+7,myobj) << '\n';
return 0;
}
The smallest element is 2
The largest element is 9
The smallest element is 2
The largest element is 9
The smallest element is 2
The largest element is 9
max_element
一样。但比较部分为(comp(*largest,*first))。
template <class ForwardIterator>
ForwardIterator max_element ( ForwardIterator first, ForwardIterator last )
{
if (first==last) return last;
ForwardIterator largest = first;
while (++first!=last)
if (comp(*largest,*first)) largest=first;
return largest;
}
next_permutation
计算序列全排列的函数,可自定义比较函数。
当当前序列不存在下一个排列时,函数返回false,否则返回true
bool next_permutation (BidirectionalIterator first,
BidirectionalIterator last);
bool next_permutation (BidirectionalIterator first,
BidirectionalIterator last, Compare comp);
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation, std::sort
bool myfunction(const int &i, const int &j) { return (i>j); }
int main() {
int myints[] = {3,2,1 };
//std::sort(myints, myints + 3);
std::cout << "The 3! possible permutations with 3 elements:\n";
do {
std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
} while (std::next_permutation(myints, myints + 3, myfunction));
std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
return 0;
}
numeric
accumulate
T accumulate (InputIterator first, InputIterator last, T init);
T accumulate (InputIterator first, InputIterator last, T init,BinaryOperation binary_op);
定义如下:
template <class InputIterator, class T>
T accumulate (InputIterator first, InputIterator last, T init)
{
while (first!=last) {
init=binary_op(init,*first); //默认累加
++first;
}
return init;
}
使用实例
// accumulate example
#include <iostream> // std::cout
#include <functional> // std::minus
#include <numeric> // std::accumulate
int myfunction (int x, int y) {return x+2*y;}
struct myclass {
int operator()(int x, int y) {return x+3*y;}
} myobject;
int main () {
int init = 100;
int numbers[] = {10,20,30};
std::cout << "using default accumulate: ";
std::cout << std::accumulate(numbers,numbers+3,init);
std::cout << '\n';
std::cout << "using functional's minus: ";
std::cout << std::accumulate (numbers, numbers+3, init, std::minus<int>());
std::cout << '\n';
std::cout << "using custom function: ";
std::cout << std::accumulate (numbers, numbers+3, init, myfunction);
std::cout << '\n';
std::cout << "using custom object: ";
std::cout << std::accumulate (numbers, numbers+3, init, myobject);
std::cout << '\n';
return 0;
}