本文全部内容来自《Professional C++》一书。对于STL进行了一些总结。
容器:
容器类名
|
类型
|
插入性能
| 删除性能 |
查找性能
|
使用情况
|
vector
|
顺序容器
|
1~n
|
1~n
|
1
|
快速查找,不在乎插入删除。
|
list
|
顺序容器
|
1
|
1
|
n
|
需要快速插入删除,不在乎查找
|
deque
|
顺序容器
|
1~n
|
1~n
|
1
|
一般不需要,可以使用list或者vector
|
queue
| 容器适配器 |
1
|
1
| - |
FIFO
|
priority_queue
|
容器适配器
|
logn
|
logn
|
-
|
带优先级的FIFO
|
stack
|
容器适配器
|
1
|
1
|
-
|
FILO
|
set/multiset
|
有序关联容器
|
logn
| logn |
logn
|
需要元素集合,对查找、插入和删除
|
map/multimap
|
有序关联容器
|
logn
|
logn
|
logn
|
希望使用键值关联
|
bitset
|
特殊
|
-
|
-
|
1
|
需要使用标志集合时使用位集
|
算法:
STL把数据容器和功能算法进行了分离。
几乎任何算法都能用于几乎仍和容器。
大约有60种算法。可以分为五大类:
工具算法、非修改算法、修改算法 、 排序算法、集合算法。
工具算法:不在数据序列上工作的算法
min、max、swap
非修改算法:
查找:
find() 查找一个特定元素
find_if() 查找第一个让if为true的词。
find_first_of()、find_last_of()查找特定位置的结果。
adjacent_find() 返回彼此相等的第一个实例。
search()、find_end() 查找特定位置的子序列。
search_n()查找等于一个给定值得n个连续元素的第一个实例 KMP算法。
lower_bound(),upper_bound(),equal_range() 给定一个查找范围。下界,上界,上下界。
binary_search() 有序序列中二分查找。
min_element(),max_element()
数值处理
count()统计与一个值匹配的个数
count_if()统计导致某个谓词返回true的元素个数。
accumkulate()默认对元素求和,但是可以提供新的二元函数。
inner_product()相乘后相加,如向量的点乘
partial_sum()生成一个新序列,其中每个元素都是源序列中相应位置上的元素及前面所有元素的和,或者其他二元操作
adjacent_difference()生成一个新序列。其中每个元素都是序列中与对应位置的前一个元素的差
比较算法
equal() 通过检查两个序列的元素顺序是否相同,即相应位置上的元素是否相同,从而确定两个序列是否相等。
mismatch()返回各个序列中与另一个序列同一个位置上的元素不匹配的第一个元素。
lexicographical_compare()第一个区间所有元素都比第二个区间中相应位置元素小,或第一个区间比第二个区间短且第一个区间元素都比第二
个区间对应位置元素小则返回true。通常作为字典序比较使用。
运算算法
for_each() 对序列中每个元素执行一个函数。打印元素时很有用。
修改算法:
transform 在每个元素或对每个元素上调用某个函数。
copy,copy_backward 将元素从一个序列复制到另一个序列。
iter_swap,swap_ranges 交换两个元素或者序列
replace,replace_if,replace_copy,replace_copy_if 将与某个值匹配或者导致一个谓词为true的所有元素
替换为一个新元素,可以就地替换,也可以将结果复制到一个新序列中。
fill,fill_n 将序列中所有元素设为一个新值
generate、generate_n()类似fill,只不过调用一个函数来生成新值。
remove,remove_if,remove _copy,remove _copy_if 删除
unique ,unique_copy 删除序列中连续的重复值
reverse ,reverse _copy 逆置
rotate ,rotate_copy 交换序列中的前一半和后一半
next_permutation,prev_permutation 得到元素的下一个排列或者前一个排列
排序算法:
sort 类似快排
stable_sort 类似归并排序
partial_sort,partial_sort_copy 对序列部分进行排序。前n个将会排序,余下元素不排序。
nth_element() 查找序列第n小的元素。
merge、inplace_merge 合并两个有序序列。
make_heap,push_heap,pop_heap,sort_heap堆排序
partition、stable_partition 对序列排序,使得谓词返回true的排在返回false之前。原序可以保持也可以不保持。
random_shuffle() 随机重新排列元素
集合算法
includes 确定一个序列是否有另一个序列的子集。
set_union,set_intersection,set_difference,set_symmetric_difference. 对两个有序序列完成指定的集合操作,将结果复制到第三个有序序列中。
STL的不足
不支持多线程。
不支持hash。
不支持图、树。
------------------------------------------------------------------------------------------------------------------------------------------------
ps: 以下代码省略std::
find() 和find_if()
在一个迭代器区间内查找一个特定元素。返回一个知识所找到的元素的迭代器或者是区间末尾的迭代器。
注意是等于函数调用中指定的末尾迭代器而不是容器的末尾迭代器。
用法示例:
#include <algorithm>
#include <vector>
find(vec.begin(),vec.end(),num);
bool isPerfect(int num)
{
return num>=100;
}
find_if (vec.begin(),vec.end(),isPerfect);
accumulate()
计算容器中所有元素的总和
#include <numeric>
#include <vector>
double sum = accumulate(numbers.begin(),numbers.end(),0);
求和需要导入numeric库而不是algorithm库。accumulate的第三个参数是总和的初始值。
函数对象
所有预定义的函数对象类都位于<functional>头文件中
算数操作符的模板有 plus,minus,multiplies,divides,modulus,negate.
#include <functional>
plus<int> myPlus;
int res = myPlus(4,5);
使用plus模板的好处在于可以作为回调传递给算法。比较运算符的模板equal_to,not_equal_to,less,greater,less_equal,greater_equal
逻辑运算符的模板logical_not,logical_and,logical_or 这三个用处不大
函数适配器
捆绑器bind2nd
find_if(vec.begin(),vec.end(),bind2nd(greater_equal<int>(),100));
查找大于等于100的数。由于greater_equal需要2个参数,而find_if只提供一个参数,所以需要使用bind2nd适配器。取反器not1
find_if(vec.begin(),vec.end(),not1(bind2nd(greater_equal<int>(),100));
小于100的数。注:这里的“1”“2” 表示操作数的数目,是一元还是二元。
工具算法
用于2个操作数:
min(a,b);
max(a,b);
swap(a,b);
adjacent_find(vec.begin(),vec.end()) ; 查找连续彼此相等的两个元素的第一个实例
min_element(vec.begin(),vec.end()) ; 查找min
max_element(vec.begin(),vec.end()) ; 查找max
find_first_of(vec.begin(),vec.end(),value1,value2)
; 查找多值中的某一个
search(vec.begin(),vec.end(),sub,sub+2) ; 查找相等的区间
比较算法
equal(vec.begin(),vec.end(),list.begin()) ; 按顺序比较两个区间中相应位置的元素,都相等返回true
mismatch(vec.begin(),vec.end(),list.begin()) ;返回不相等的第一个位置
lexicographical_compare(vec.begin(),vec.end(),list.begin()) ;字典序比较,区间1小返回true。
运算算法
for_each() 是STL中最常用的算法,对区间内所有元素执行一个回调
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void print(int & elem)
{
cout<<elem<<endl;
}
int main(int argc ,char** argv)
{
vector<int> vec;
vec.push_back(1);
vec.push_back(3);
for_each(vec.begin(),vec.end(),&print);
}
修改算法
修改算法都有source和destination的概念,可以源和目的一致即执行就地修改(in place)
转换 transform()
transform(vec.begin(),vec.end(),<span style="font-family: Arial, Helvetica, sans-serif;">vecDest</span>.begin(),bind2nd(plus<int>(),100));
复制 copy() copy(vec.begin(),vec.end(),vecDest.begin());
替换 replace(),replace_if()把一个区间分别与特定值或者某个谓词匹配的元素替换为一个新值。
replace(vec.begin(),vec.end(),50,0);
replace_if(vec.begin(),vec.end(),bind2nd(less<int>(),0),0);
删除remove(),remove_if()从一个区间删除某些元素,可以用特定值或者谓词指定。
这些元素不会从容器中删除,算法只能访问迭代器抽象,不会访问容器。
所删除的元素会复制到区间的最后,并返回一个新的区间末尾(比原来还要短)。
容器执行erase()删除元素。
#include <vector>
#include <algorithm>
#include <iostream>
#include <functional>
#include <string>
using namespace std;
void print(const string& str)
{
cout<<str<<endl;
}
int main(int argc ,char** argv)
{
vector<string> vec;
vec.push_back("s1");
vec.push_back("");
vec.push_back("s2");
vec.push_back("");
vec.push_back("s3");
vec.push_back("");
auto it = remove_if(vec.begin(),vec.end(),mem_fun_ref(&string::empty));
vec.erase(it,vec.end());
for_each(vec.begin(),vec.end(),&print);
}
remove的变种有remove_copy()和remove_copy_if()他们不修改源区间,会把未删除的元素复制到一个不同的目标区间remove是稳定的算法,移动后之前的元素顺序依然保持。
唯一unique()
删除所有重复连续元素。
逆置reverse()
逆序排列区间内元素。
排序算法
排序 sort(vec.begin(),vec.end()); 非递减排序
合并 merge(vec1.begin(),vec1.end(),vec2.begin(),vec2.end(),vecDest.begin()); 合并两个有序区间,合并后依然有序。
堆排序算法 make_heap(),push_heap(),pop_heap(),sort_heap().
堆排序算法 make_heap(),push_heap(),pop_heap(),sort_heap().
随机排序 random_shuffle() 反排序算法,随机重新排列元素。即洗牌算法。
集合算法
set_union() 合集
set_intersection() 交集
set_difference() 差集
set_symmetric_difference() 类似异或,即合集减去交集那部分