accumulate
累加
该算法作用是对某区间中的元素进行累加,使用时必须添加头文件<numeric>
;
template < class InputIterator , class T >
T accumulate ( InputIterator first, InputIterator last, T init) ;
template < class InputIterator , class T , class BinaryOperation >
T accumulate ( InputIterator first, InputIterator last, T init, BinaryOperation binary_op) ;
struct Mul2 {
int operator ( ) ( int x, int y) { return x + 2 * y; }
} ;
int main ( ) {
vector< int > v{ 10 , 20 , 30 } ;
cout << accumulate ( v. begin ( ) , v. end ( ) , 0 ) << endl;
cout << accumulate ( v. begin ( ) , v. end ( ) , 0 , Mul2 ( ) ) << endl;
return 0 ;
}
count
与count_if
计数
该算法的作用是统计某区间中某个元素出现的次数,使用时必须添加头文件<algorithm>
;
template < class InputIterator , class T >
ptrdiff_t count ( InputIterator first, InputIterator last, const T& value) ;
template < class InputIterator , class Predicate >
ptrdiff_t count_if ( InputIterator first, InputIterator last, Predicate pred) ;
bool IsOdd ( int i) {
return ( ( i % 2 ) == 1 ) ;
}
int main ( ) {
vector< int > v1{ 10 , 20 , 30 , 30 , 20 , 10 , 10 , 20 } ;
cout << count ( v1. begin ( ) , v1. end ( ) , 10 ) << endl;
vector< int > v2{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
cout << count_if ( v2. begin ( ) , v2. end ( ) , IsOdd ( ) ) << endl;
return 0 ;
}
find
与find_if
查找
该算法的作用是找元素在区间中第一次出现的位置,使用时必须包含头文件<algorithm>
;
template < class InputIterator , class T >
InputIterator find ( InputIterator first, InputIterator last, const T& value ) ;
template < class InputIterator , class Predicate >
InputIterator find_if ( InputIterator first, InputIterator last, Predicate pred) ;
max
与min
最值
max
返回两个元素中较大值,min
返回两个元素中较小值,使用时必须包含头文件<algorithm>
;
template < class T >
const T& max ( const T& a, const T& b) ;
template < class T >
const T& min ( const T& a, const T& b) ;
merge
合并
该算法作用将两个有序序列合并成一个有序序列,使用时必须包含头文件<algorithm>
;
template < class InputIterator1 , class InputIterator2 , class OutputIterator >
OutputIterator merge ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) ;
int main ( ) {
vector< int > v{ 2 , 6 , 5 , 8 } ;
list< int > L{ 9 , 3 , 0 , 5 , 7 } ;
sort ( v. begin ( ) , v. end ( ) ) ;
L. sort ( ) ;
vector< int > vRet ( v. size ( ) + L. size ( ) ) ;
merge ( v. begin ( ) , v. end ( ) , L. begin ( ) , L. end ( ) , vRet. begin ( ) ) ;
for ( auto e : vRet)
cout << e << " " ;
cout << endl;
return 0 ;
}
partial_sort
前K个最值
该算法的作用是找前 K 个最大 / 小的元素,使用时必须包含头文件<algorithm>
;
template < class RandomAccessIterator >
void partial_sort ( RandomAccessIterator first, RandomAccessIterator middle,
RandomAccessIterator last) ;
template < class RandomAccessIterator , class Compare >
void partial_sort ( RandomAccessIterator first, RandomAccessIterator middle,
RandomAccessIterator last, Compare comp) ;
原理:partial_sort
的实现原理是:对原始容器内区间为 [first, middle) 的元素执行make_heap()
操作,构造一个最大堆,然后拿 [middle, last) 中的每个元素和 first 进行比较,first 内的元素为堆内的最大值,如果小于该最大值,则互换元素位置,并对 [first, middle) 内的元素进行调整,使其保持最大堆序。比较完之后再对 [first, middle) 内的元素做一次堆排序sort_heap()
操作,使其按增序排列; 举例:
int main ( ) {
vector< int > v1{ 4 , 1 , 8 , 0 , 5 , 9 , 3 , 7 , 2 , 6 } ;
partial_sort ( v1. begin ( ) , v1. begin ( ) + 4 , v1. end ( ) ) ;
vector< int > v2{ 4 , 1 , 8 , 0 , 5 , 9 , 3 , 7 , 2 , 6 } ;
partial_sort ( v2. begin ( ) , v2. begin ( ) + 4 , v2. end ( ) , greater< int > ( ) ) ;
return 0 ;
}
partition
划分
该算法的作用是按照条件对区间中的元素进行划分,使用时必须包含头文件<algorithm>
;
template < class BidirectionalIterator , class Predicate >
BidirectionalIterator partition ( BidirectionalIterator first, BidirectionalIterator last, Predicate pred) ;
bool IsOdd ( int i)
{ return ( i % 2 ) == 1 ; }
int main ( ) {
vector< int > v{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
auto div = partition ( v. begin ( ) , v. end ( ) , IsOdd) ;
for ( auto it = v. begin ( ) ; it != div; ++ it)
cout << * it << " " ;
cout << endl;
for ( auto it = div; it != v. end ( ) ; ++ it)
cout << " " << * it;
cout << endl;
return 0 ;
}
reverse
逆置
该算法的作用是对区间中的元素进行逆置,使用时必须包含头文件<algorithm>
;
template < class BidirectionalIterator >
void reverse ( BidirectionalIterator first, BidirectionalIterator last) ;
sort
排序
排序在实际应用中需要经常用到,而在目前的排序中,快排平均情况下是性能最好的一种排序,但是快排也有其自身的短板,比如说:元素接近有序、元素量比较大的情况下,直接使用快排时,堪称一场灾难,因此 STL 中sort
算法并没有直接使用快排,而是针对各种情况进行了综合考虑,下面关于sort
函数分点进行说明:
sort
函数提供了两个版本:
sort(first, last)
:默认按照小于方式排序,排序结果为升序,一般用排内置类型数据sort(first, last, comp)
:可以通过 comp 更改元素比较方式,即可以指定排序的结果为升序或者降序,一般以仿函数对象和函数指针的方式提供; sort
并不是一种排序算法,而是将多个排序算法混合而成;当元素个数少于__stl_threshold
阈值时 (这个值为 16),使用直接插入排序处理; 当元素个数超过__stl_threshold
时,考虑是否能用快排的方式排序,因为当元素数量达到一定程度,递归式的快排可能会导致栈溢出而崩,因此:
通过__lg
函数判断递归的深度; 如果递归的深度没有超过 2 * log2 N 时,则使用快排方式排序,注意:快排时使用到了三数取中法预防分割后,一边没有数据的极端情况; 如果递归深度超过 2 * log2 N 时,说明数据量大,递归层次太深,可能会导致栈溢出,此时使用堆排序处理;
unique
去重
该函数的作用是删除区间中相邻的重复性元素,确保元素唯一性,注意在使用前要保证区间中的元素是有序的,才能达到真正的去重,使用时必须包含头文件<algorithm>
; 注意:
该函数并不是将重复性的元素删除掉,而是用后面不重复的元素将前面重复的元素覆盖掉了; 返回值是一个迭代器,指向的是去重后容器中不重复最后一个元素的下一个位置; 该函数需要配合erase
才能真正的将元素删除掉;
template < class ForwardIterator >
ForwardIterator unique ( ForwardIterator first, ForwardIterator last) ;
template < class ForwardIterator , class BinaryPredicate >
ForwardIterator unique ( ForwardIterator first, ForwardIterator last,
BinaryPredicate pred) ;
int main ( ) {
vector< int > v{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 } ;
auto it = unique ( v. begin ( ) , v. end ( ) ) ;
for ( auto e : v)
cout << e << " " ;
cout << endl;
v. erase ( it, v. end ( ) ) ;
for ( auto e : v)
cout << e << " " ;
cout << endl;
sort ( v. begin ( ) , v. end ( ) ) ;
for ( auto e : v)
cout << e << " " ;
cout << endl;
it = unique ( v. begin ( ) , v. end ( ) ) ;
v. erase ( it, v. end ( ) ) ;
for ( auto e : v)
cout << e << " " ;
cout << endl;
return 0 ;
}
next_permutation
与pre_permutation
全排列
next_permutation
是获取一个排序的下一个排列,可以遍历全排列,prev_permutation
刚好相反,获取一个排列的前一个排列, 使用时必须包含头文件<algorithm>
;举例:
int main ( ) {
vector< int > v = { 4 , 1 , 2 , 3 } ;
sort ( v. begin ( ) , v. end ( ) ) ;
do {
cout << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << " " << v[ 3 ] << endl;
} while ( next_permutation ( v. begin ( ) , v. end ( ) ) ) ;
cout << endl;
sort ( v. begin ( ) , v. end ( ) , greater< int > ( ) ) ;
do {
cout << v[ 0 ] << " " << v[ 1 ] << " " << v[ 2 ] << " " << v[ 3 ] << endl;
} while ( prev_permutation ( v. begin ( ) , v. end ( ) ) ) ;
return 0 ;
}