STL 算法整理 - STEMHA's Blog

STL 算法整理

标准库中常见的函数与头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<cstdlib>: abort,
<numeric>: accumulate, inner_product,
<memory>: allocator, auto_ptr, uninitialized_copy,
<iterator>: back_inserter, front_inserter, inserter, istream_iterator, ostream_iterator, reverse_iterator,
<new>: bad_alloc,
<typeinfo>: bad_cast, type_info,
<functional>: bind2nd, less_equal, negate, not1, plus,
<bitset>: bitset,
<iostream>: boolalpha, cerr, cin, cout, dec, endl, ends, fixed, flush, hex, internal, istream, left, noboolalpha, noshowbase, noskipws, nounitbuf, nouppercase, oct, ostream, right, scientific, showbase, sowpoint, skippws, unitbuf, uppercase
<algorithm>: copy, count, count_if, equal_range, fill, fill_n, find, find_end, find_first_of, for_each, max, main, nth_element, partial_sort, replace, replace_copy, set_difference, set_intersection, set_union, sort, stable_sort, unique, unique_copy, upper_bound,
<deque>: deque,
<exception>: exception, unexpected,
<fstream>: fstream, ifstream, ofstream,
<string>: getline, string,
<ios_base>: ios_base,
<cctype>: isalpha, islower, ispunct, isspace, isupper,
<sstream>: istringstream, ostringstream, stringstream,
<list>: list,
<stdexcept>: logic_error, out_of_range, range_error, runtime_error,
<utility>: make_pair, pair,
<map>: map, multimap
<set>: multiset, set
<queue>: priority_queue, queue
<cstddef>: ptrdiff_t, size_t,
<iomanip>: setfill, setprecision, setw,
<cmath>: sqrt,
<stack>: stack,
<cstring>: strcmp, strcpy, strlen, strncpy,
<vector>: vector

标准库定义了 100多个算法,要学习如何使用它们,需要理解它们的结构,而不是记住每个算法的细节。

  • beg和end表示元素范围的迭代器
  • beg2表示第二个序列开始位置迭代器,end2表示第二个序列末尾迭代器(如果有)。如没有则假定系列2至少与beg end表示的范围一样大。beg和beg2类型不必匹配,但必须保证两个序列中的元素可以执行特性操作或调用给定的可调用对象。
  • des表示目的序列的迭代器,目的序列保证有足够的空间存放算法生成的元素。
  • unaryPred和binaryPred是一元和二元谓词,分别接受来自输入序列的元素,两个谓词都返回可用作条件的类型。
  • comp是一个二元谓词,满足关联容器中对关键字序的要求
  • unaryOp和binaryOp是可调用对象,分别使用来自输入序列的一个和两个实参来调用。

查找对象的算法:

find

1
2
find(beg,end,val);           在迭代区间[begin,end)内查找等于val的元素,找到返回相应的迭代器,否则返回end。
find_if(beg,end,unaryPred); 函数find的带一个函数参数的_if版本,条件:使函数unaryPred返回true

find_first_of/find_end

1
2
3
find_first_of(beg1,end1,beg2,end2);
find_first_of(beg1,end1,beg2,end2,binaryPred);
依次遍历元素,在[beg1, end1)中查找首次出现[beg2, end2)中的任一元素,使用==或unarypred相匹配。//注意是任意一个匹配即可。

例:vec1 –{1,2,3,4,5}, vec2{3,2,4}, vec3{8,6,7}
在vec1中查找vec2,则返回元素2在vec1中的迭代器。
在vec1中查找vec3,则返回vec1.end()迭代器。

1
2
3
4
find_end(beg1,end1,beg2,end2);
find_end(beg1,end1,beg2,end2,binaryPred);
在[beg1,end1)范围内查找[beg2,end2)最后一次出现。找到则返回最后一对的第一个ForwardIterator,否则返回end1。
依次遍历元素,在[beg1, end1)中查找最后一个匹配的子序列[beg2, end2),若存在,则返回beg2在[beg1, end1)中对应的迭代器,否则返回end1。[beg2, end2)中序列必须完全匹配。

例:vec1 –{1,2,3,4,5}, vec2{2,3,4}, vec3{3,2,4}
在vec1中查找vec2,则返回元素2在vec1中的迭代器。
在vec1中查找vec3,则返回vec1.end()迭代器。

adjacent_find

1
2
adjacent_find(beg,end);
adjacent_find(beg,end,binaryPred);

依次遍历元素,查范围内相邻元素,使用==或unarypred相匹配,若存在,返回第一个元素对应的迭代器,否则返回end.

1
2
3
4
5
6
7
search(beg1,end1,beg2,end2);
search(beg1,end1,beg2,end2,binaryPred);
依次遍历元素,在[beg1, end1)中查找第一个匹配的子序列[beg2, end2)。若存在,则返回beg2在[beg1, end1)中对应的迭代器,否则返回end1。[beg2, end2)中序列必须完全匹配。

search_n(beg,end,count,val); //找第n个匹配的
search_n(beg,end,count,val,binaryPred);
依次遍历元素,在[beg1, end1)中查找匹配val的元素,使用==或unarypred匹配。若存在,返回count指定的第count个元素所对应的迭代器,否则返回end1。若count指定值为负数或0,则返回beg1。

count

1
2
3
count(beg,end,val);
count_if(beg,end,unaryPred);
依次遍历元素,查找范围内与val相匹配或使unarypred为真的元素个数。

其他只读算法:

for_each

1
2
for_each(beg,end,f); 	     
将[beg,end)范围内所有元素依次调用函数func,返回func。不修改序列中的元素。

mismatch

1
2
3
4
mismatch(beg1,end1,beg2);
mismatch(beg1,end1,beg2,binaryPred);
并行比较[beg1,end1)与[beg2,end2),指出第一个不匹配的位置,返回一对iterator,标志第一个不匹配元素位置。
如果都匹配,返回每个容器的end。

equal

1
2
3
判断[beg1,end1)与[beg2,end2)内元素都相等
equal(beg1,end1,beg2);
equal(beg1,end1,beg2,binaryPred);

二分查找算法:

lower_bound/upper_bound

lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。

1
2
3
4
5
6
7
8
9
lower_bound(beg,end,val);
lower_bound(beg,end,val,comp);
从[beg,end)位置二分查找第一个大于或等于val的数字,找到返回该数字的地址,不存在则返回end。
通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound(beg,end,val);
upper_bound(beg,end,val,comp);
从[beg,end)位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。
通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

equal_range

返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。

1
2
equal_range(beg,end,val);
equal_range(beg,end,val,comp);

在[beg,end)中查找val,找到返回true。

1
2
binary_search(beg,end,val);
binary_search(beg,end,val,comp);

写容器元素的算法:

fill_n/fill

1
2
fill_n(dest,cnt,val); 将值val赋给[beg,beg+n)范围内的所有元素。
fill(beg,end,val); 将值val赋给[beg,end)范围内的所有元素。

generate_n/generate

连续调用函数func填充[beg,end)范围内的所有元素。

1
2
generate_n(dest,cnt,Gen);
generate(beg,end,Gen);

copy/copy_n

复制[beg,end)到res

1
2
3
copy(beg,end,dest);
copy_backward(beg,end,dest);
dest是输出序列的尾后迭代器。输入范围内的元素被拷贝或移动到目的序列的尾元素,然后是倒数第二个,类推。返回从beg拷贝或移动的元素的位置。如范围为空则返回dest

transform

1
2
3
4
将[beg,end)范围内所有元素依次调用函数unary,结果放入res中。
transform(beg,end,dest,unaryOp);
transform(beg,end,beg2,dest,binaryOp);
将[beg,end)范围内所有元素与[beg2,beg2+end-beg)中所有元素依次调用函数unary,结果放入res中。

replace_copy

将[beg,end)内所有等于oval的元素都用nval代替.将结果写入res。

1
2
replace_copy(beg,end,dest,old_val,new_val);
replace_copy_if(beg,and,dest,unaryPred,new_val);

replace_if/replace

将[beg,end)内所有等于old_val的元素都用nval代替

1
2
replace(beg,end,old_val,new_val);
replace_if(beg,end,unaryPred,new_val);

merge

1
2
merge(beg1,end1,beg2,end2,dest); 合并[beg1,end1)与[beg2,end2)存放到res。
merge(beg1,end1,beg2,end2,dest,comp);

swap/swap_ranges

1
2
3
swap(elem1,elem2);
swap_ranges(beg1,end1,beg2);
iter_swap(iter1,iter2);

inplace_merge

合并[beg,mid)与[mid,end),结果覆盖[beg,end)。

1
2
inplace_merge(beg,mid,end);
inplace_merge(beg,mid,end,comp);

划分与排序算法:

partial_sort和nth_element只进行部分排序,速度比整体排序算法更快。

partition

1
2
stable_partition(beg,end,unaryPred); 与partition()类似,保留容器中的相对顺序。
partition(beg,end,unaryPred); 元素重新排序,使用pred函数,把结果为true的元素放在结果为false的元素之前。

sort/stable_sort

1
2
3
4
sort(beg,end); 默认升序重新排列元素
sort(beg,end,comp);
stable_sort(beg,end); 与sort()类似,保留相等元素之间的顺序关系。
stable_sort(beg,end,comp);

partial_sort/partial_sort_copy

1
2
3
4
5
6
partial_sort(beg,mid,end); 排序mid-beg个元素。排序后,从beg到mid中的元素都是有序的,mid到end中的元素顺序未指定。
partial_sort(beg,mid,end,comp);
partial_sort_copy(beg,end,destBeg,destEnd);
partial_sort_copy(beg,end,destBeg,destEnd,comp);
排序输入范围内的元素,并将足够多的元素拷贝到destBeg和destEnd所指示的序列中。如果目的序列大于等于输入范围则排序整个输入序列并存入输出序列,若目的序列小于输入范围,则拷贝输入序列中与目的范围一样多的元素。
返回一个迭代器,指向目的范围中已排序部分的尾后迭代器。如目的序列小于等于输入范围,则返回destEnd(此时是否整个输入序列排序???)。

nth_element

单个元素序列重新排序,使所有小于第n个元素的元素都出现在它前面,而大于它的都出现在后面。

1
2
nth_element(beg,nth,end);
nth_element(beg,nth,end,comp);

通用重新排序算法:

remove/remove_copy

1
2
3
4
5
6
7
删除[beg,end)内所有等于val的元素。注意,该函数不是真正删除函数。
采用的办法是:用保留的元素覆盖要删除的元素。算法返回一个迭代器,指向最后一个保留元素的尾后位置。
remove(beg,end,val);
remove_if(beg,end,unaryPred);
remove_copy(beg,end,dest,val);
remove_copy_if(beg,end,dest,unaryPred);
将所有不等于val元素复制到res,返回OutputIterator指向被拷贝的末元素的下一个位置。

unique

1
2
3
4
5
6
重排序列,对于相邻的满足条件的元素,通过覆盖来进行删除,返回一个迭代器,指向最后一个保留元素的尾后位置。
unique(beg,end);
unique(beg,end,binaryPred);
unique_copy(beg,end,dest);
unique_copy(beg,end,dest,binaryPred);
与unique类似,不过把结果输出到dest。

rotate

围绕mid指向的元素进行元素转动。元素mid成为首元素,随后是mid+1->end之间的之前的元素,再接着是beg到mid之前的元素。返回一个迭代器,指向原来beg位置的元素。

1
2
rotate(beg,mid,end);
rotate_copy(beg,mid,end,dest);

reverse

翻转序列中的元素。reverse返回void,reverse_copy返回一个迭代器,指向拷贝到目的序列的元素的尾后位置。

1
2
reverse(beg,end);
reverse_copy(beg,end,dest);

random_shuffle

使用随机访问迭代器的重排算法

1
2
random_shuffle(beg,end); 元素随机调整次序。
random_shuffle(beg,end,rand); 使用函数gen代替随机生成函数执行random_shuffle()。

排列算法:

这些算法假定序列中的元素都是唯一的。要求双向迭代器。

is_permutation

判断两个序列是否为同一元素集的不同排列

1
2
is_permutation(beg1, end1, beg2)
is_permutation(beg1, end1, beg2, binaryPred)

next_permutation

生成序列的字典序排列中的下一个,返回要给bool指出是否还有下一个
如果序列已经是最后一个排序,则本函数将序列重排为最小的序列,返回false。否则将输入序列转为字典序的下一个排列,返回true。

1
2
next_permutation(beg,end);
next_permutation(beg,end,comp);
1
2
3
4
5
6
int a[6]={1,2,3,4,5,6};
do{
for(int i=0;i<6;i++)
cout<<a[i]<<' ';
cout<<endl;
}while(next_permutation(a,a+6));

prev_permutation

生成序列的字典序排列中的前一个,返回要给bool指出是否还有前一个。
若序列已经是第一个排序,则本函数将序列重排为最大的序列,返回false。否则将序列转为字典序的上一个排序,返回true。

1
2
prev_permutation(beg,end);
prev_permutation(beg,end,comp);

有序序列的集合算法:

includes

判断[beg1,end1)是否包含[beg2,end2),使用底层元素的<操作符,成功返回true。重载版本使用用户输入的函数。

1
2
includes(beg,end,beg2,end2);
includes(beg,end,beg2,end2,comp);

set_union

取[beg1,end1)与[beg2,end2)元素并集存放到dest。

1
2
set_union(beg,end,beg2,end2,dest);
set_union(beg,end,beg2,end2,dest,comp); 将函数comp代替<操作符,执行set_union()

set_intersection

取[beg1,end1)与[beg2,end2)元素交集存放到res。

1
2
set_intersection(beg,end,beg2,end2,dest);
set_intersection(beg,end,beg2,end2,dest,comp); 将函数comp代替<操作符

set_difference

取[beg1,end1)与[beg2,end2)元素内差集存放到res。

1
2
set_difference(beg,end,beg2,end2,dest);
set_difference(beg,end,beg2,end2,dest,comp); 将函数comp代替<操作符

set_symmetric_difference

取[beg1,end1)与[beg2,end2)元素外差集存放到res。

1
2
set_symmetric_difference(beg,end,beg2,end2,dest);
set_symmetric_difference(beg,end,beg2,end2,dest,comp);

最大值和最小值算法:

min/max

1
2
3
4
min(va1,va2);            返回两个元素中较小一个。
min(val1,val2,comp);
max(val1,val2);
max(val1,val2,comp); 返回两个元素中较大一个。

min_element/max_element

1
2
3
4
min_element(beg,end);    返回一个ForwardIterator,指出[beg,end)中最大的元素。
min_element(beg,end,comp);
max_element(beg,end); 返回一个ForwardIterator,指出[beg,end)中最小的元素。
max_element(beg,end,comp);

lexicographical_compare

1
2
lexicographical_compare(beg1,end1,beg2,end2);      按字典序判断[beg1,end1)是否小于[beg2,end2)
lexicographical_compare(beg1,end1,beg2,end2,comp); 将函数comp代替<操作符

算术算法:< numeric >

accumulate

1
2
3
4
对[beg,end)内元素之和,加到初始值val上。
accumulate(beg,end,init);
accumulate(beg,end,init,BinaryOp);
将函数BinaryOp代替加法运算,执行accumulate()。

partial_sum

1
2
3
将[beg,end)内该位置前所有元素之和放进dest中。
partial_sum(beg,end,dest);
partial_sum(beg,end,dest,BinaryOp);

inner_product

1
2
3
对两个序列做内积(对应元素相乘,再求和)并将内积加到初始值init上。
inner_product(beg1,end1,beg2,init);
inner_product(beg1,end1,beg2,init,BinOp1,BinOp2);

adjacent_difference

将新序列写入dest,每个新元素(除了首元素)的值都为输入范围中当前位置和前一个位置元素之差。第一个版本使用-,第二个版本使用binaryOp。

1
2
adjacent_difference(beg,end,dest);
adjacent_difference(beg,end,dest,BinaryOp);

参考资料

C++ primer 附录
C++ STL 常见算法(比较详细)
C++进阶:STL算法总结
C/C++基础—算法概览
关于lower_bound( )和upper_bound( )的常见用法

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×