To-Do:
STL算法概念:
-
STL中的算法是泛型算法, 独立于底层的数据类型, 同时独立于容器类型
-
不同的都算法提供了通用的迭代器接口, 用于与不同的数据类型与容器类型连接
-
大多数算法允许用户自定义规则
如用户可以通过提供回调函数, 利用函数指针或函数对象, 自定义算法的操作行为, 如sort的排序规则
使用STL泛型算法需要 #include <algorithm>
几个典型算法:
find算法:
- find算法在指定的迭代器区间查找特定元素,find算法可施加于任意容器
- 若找到元素,返回引用该元素的迭代器
若未找到元素,返回迭代器区间的末尾 - 时间复杂度为o(n)
其模板定义:
template <class InputIterator, class T>
InputIterator find
(InputIterator first, InputIterator last, const T& val);
- InputIterator first & InputIterator last
头两个模板参数为查找的区间的迭代器, 同样为半开半闭区间 - val
为需要查找的值
find_if算法:
- 与find算法类似,find_if也可以实现元素查找
- find_if对迭代器区间的每个元素调用判定式,当返回true时,表示找到匹配的元素
模板定义:
template <class InputIterator, class UnaryPredicate>
InputIterator find_if
(InputIterator first, InputIterator last, UnaryPredicate pred);
- InputIterator first & InputIterator last
头两个参数和find相同, 都是查找的区间的迭代器 - UnaryPredicate pred
为用户提供的一个用于匹配的判定标准
可以是4种可调用对象的任意一种
find_if的功能等价于:
template<class InputIterator, class UnaryPredicate>
InputIterator find_if
(InputIterator first, InputIterator last, UnaryPredicate pred)
{
while (first!=last) {
if (pred(*first)){ //可以看到其对区间内的每一个元素调用判定式
return first;
}
++first;
}
return last;
}
accumulate算法:
模板定义:
//sum (1)
template <class InputIterator, class T>
T accumulate (InputIterator first, InputIterator last, T init);
//custom (2)
template <class InputIterator, class T, class BinaryOperation>
T accumulate (InputIterator first, InputIterator last, T init,
BinaryOperation binary_op);
- InputIterator first & InputIterator last
指定相加的区间的迭代器 - T init
为开始累加的初始值 - BinaryOperation binary_op
所调用的具体的计算的方式 (默认为累加)
accumulate的功能等价于:
template <class InputIterator, class T>
T accumulate (InputIterator first, InputIterator last, T init)
{
while (first!=last) {
init = init + *first; // or: init=binary_op(init,*first) for the binary_op version
++first;
}
return init;
}
可以看到
- 当不提供BinaryOperation binary_op时, 其默认的计算方式为累加
- 当提供了BinaryOperation binary_op后, 会对其区间内的每一个元素调用binary_op
通用算法&容器算法:
通用算法由于其通用的特性, 需要适应更多的数据类型, 所以在效率上做出了一些牺牲, 故相比于容器算法, 在效率上没有后者高
所以:
- 当STL通用算法和特定容器的方法实现相同功能的情况下,优先使用容器的方法,效率更高
如STL中的find算法, 时间复杂度为o(n), 而map自带的find算法, 时间复杂度为o(log N)
STL算法的使用:
可调用对象:
首先, 之前说到的用户可以通过自定义回调函数来控制算法的规则, 而回调函数是可调用对象的一种
可调用对象主要应用与传递给泛型算法作为算法内部的规则
在STL的多种算法中,都可以传递可调用对象,根据指定的规则进行比较判断
4类可调用对象:
- 函数或函数指针(函数名)
- 指向成员函数的指针
- 函数对象:实现了operator()的类的对象
- Lambda表达式,匿名的函数对象
函数对象:
首先, 函数&函数指针&成员函数, 这三个都很熟悉, 就不进行详细讨论了, 主要探讨新的东西
其实, 函数对象也在前头讨论过, 就是重载了operator() 的类, 这里直接Copy之前的内容:
3. 圆括号()函数调用运算符的重载:
当重载函数调用运算符时, 并非创造了一种新的调用函数的方式,相反地,这是创建一个可以传递任意数目参数的运算符函数, 而其相应的类被称作 "函数对象"
即可以像使用函数一样直接使用类对象, 并向其传递特定数目和类型的参数, 编译器会调用不同的重载函数完成相应的操作, 并且是唯一一种支持形参缺省值的运算符重载通常, 函数对象中的数据成员被用于定制operator()函数调用运算符中的一些操作, 并且函数对象经常作为泛型算法的实参被传递(这个先等等…水很深的…)
总之函数调用运算符的重载拓宽了设计者的创作空间
//类内定义: void operator () (int n1=0,int n2=0){ //支持提供缺省值的方式 cout<<"Operator () Overload\n"; num=n1+n2; return ; } //使用: class student stuObj1(student(250)); stuObj1(1,2); cout<<stuObj1<<endl;
输出结果:
Overload Constructor: int
Operator () Overload
operator <<
3
STL中的函数对象:
STL中提供了多个函数对象类,实现基本的运算
使用STL函数对象需要 #include <functional>
算数类函数对象:
5个类都是基于模板的类,真正的运算由包装的数据类型实现
- plus
- minus
- multiplies
- divides
- modulus
如:
#include <functional>
#include <iostream>
using namespace std;
int main()
{
plus<int> myPlus; //首先是使用模板定义类对象
int res = myPlus(4, 5); //而后的使用就基本和普通函数相同
cout << res << endl;
return 0;
}
double geometricMean(const vector<int>& nums)
{
double mult = accumulate(nums.begin(),
nums.end(), 1, multiplies<int>() );
return (pow(mult, 1.0 / nums.size()));
}
比较类函数对象类:
对于priority_queue优先队列、关联容器,需要提供比较类函数对象,实现排序时的比较运算
6个比较类函数对象类:
- equal_to
- not_equal_to
- less
- greater
- less_equal
- greater_equal
priority_queue优先队列的模板定义:
template <class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
//其中的value_type 是The first template parameter (T)
//如priority_queue<int> , 这里的Container::value_type就为int
可以看出, priority_queue默认使用的是less类对象, 如果需要其他规则, 使用比较类函数对象类较为方便
//priority_queue的默认状态
int main(){
priority_queue<int> myQueue;
myQueue.push(3);
myQueue.push(4);
myQueue.push(2);
myQueue.push(1);
while (!myQueue.empty()) {
cout << myQueue.top() << endl;
myQueue.pop();
}
return 0;
}
//修正后的状态:
int main(){
//第一个参数:指定元素类型为int, 即T=int
//第二个参数:指定底层容器类型为vector<int>, 即vector<T>
//第三个参数:指定比较用的函数对象类为greater<int>, 即greater<Container::value_type>
priority_queue<int, vector<int>, greater<int> > myQueue;
myQueue.push(3);
myQueue.push(4);
myQueue.push(2);
myQueue.push(1);
while (!myQueue.empty()) {
cout << myQueue.top() << endl;
myQueue.pop();
}
return 0;
}
函数对象适配器:
某些算法中,STL现有的函数对象无法匹配
如find_if算法只给回调函数传递一个参数, 这对于需要两个参数的课调用对象就不使用, 因为参数个数无法匹配
函数对象适配器试图解决这些问题,通过函数对象的组合,创建满足需求的行为
实际上就是补充一个缺少的参数
常见的函数对象适配器:
- bind1st
- bind2nd
- not1
- not2
但是在C++中不推荐使用bind1st & bind2nd, 因为已经有了替代的方案: bind
bind2nd:
模板定义:
template <class Operation, class T>
binder2nd<Operation> bind2nd (const Operation& op, const T& x);
如:
vector<int>::iterator it = find_if(
myVector.begin(), myVector.end(),
bind2nd(greater_equal<int>(), 100));
bind2nd将find_if传入的参数绑定到了greater_equal的第二个参数上, 而100则作为了greater_equal的第一个参数, 由此就可以满足find_if只传入一个参数, 而greater_equal需要两个参数的矛盾
bind2nd功能上相当于:
template <class Operation, class T>
binder2nd<Operation> bind2nd (const Operation& op, const T& x)
{
return binder2nd<Operation>(op, typename Operation::second_argument_type(x));
}
//其中的binder2nd:
template <class Operation> class binder2nd;
//功能等价:
template <class Operation> class binder2nd
: public unary_function <typename Operation::first_argument_type,
typename Operation::result_type>
{
protected:
Operation op;
typename Operation::second_argument_type value;
public:
binder2nd ( const Operation& x,
const typename Operation::second_argument_type& y) : op (x), value(y) {}
typename Operation::result_type
operator() (const typename Operation::first_argument_type& x) const
{ return op(x,value); }
};
bind:
Since C++11
- bind可以理解为一个通用的函数适配器
其接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表
bind模板定义:
//simple(1)
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
//with return type (2)
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
看的很懵, 其实是这样的:
调用bind的一般形式:
auto newCallable = bind(callable,arg_list);
- newCallable本身是一个可调用对象
- arg_list是一个逗号分隔的参数列表
其中可以包含占位符placeholders::_n
, 用来确定调用newCallable后传入的参数绑定的位置 - 对应给定的callable的参数
当调用newCallable时,newCallable会调用callable, 并传给它arg_list中的参数:
//定义:
auto newCallable = bind(callable,placeholder::_1, placeholder::_2, 789);
//调用:
newCallable(123, 456);
调用newCallable后, 123传递给callable的第一个参数, 456传递给callable的第二个参数, 而789为第三参数
以下是两个使用例程:
void func(int num, const string& str){
cout<<num<<","<<str<<endl;
}
int main(void){
string str="abc";
auto f1=bind(func, placeholders::_1,str);
f1(16);
return 0 ;
}
#include <iostream>
#include <functional>
using namespace std;
class A
{
public:
void fun_3(int k,int m)
{
cout<<"print: k="<<k<<",m="<<m<<endl;
}
};
void fun_1(int x,int y,int z)
{
cout<<"print: x=" <<x<<",y="<< y << ",z=" <<z<<endl;
}
void fun_2(int &a,int &b)
{
a++;
b++;
cout<<"print: a=" <<a<<",b="<<b<<endl;
}
int main(int argc, char * argv[])
{
//f1的类型为 function<void(int, int, int)>
auto f1 = std::bind(fun_1,1,2,3);
//表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3
f1();
//print: x=1,y=2,z=3
auto f2 = std::bind(fun_1, placeholders::_1,placeholders::_2,3);
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f2 的第一,二个参数指定
f2(1,2);
//print: x=1,y=2,z=3
auto f3 = std::bind(fun_1,placeholders::_2,placeholders::_1,3);
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f3 的第二,一个参数指定
//注意: f2 和 f3 的区别。
f3(1,2);
//print: x=2,y=1,z=3
int m = 2;
int n = 3;
auto f4 = std::bind(fun_2, placeholders::_1, n);
//表示绑定fun_2的第一个参数为n, fun_2的第二个参数由调用f4的第一个参数(_1)指定。
f4(m);
//print: m=3,n=4
cout<<"m="<<m<<endl;
//m=3 说明:bind对于不事先绑定的参数,通过std::placeholders传递的参数是通过引用传递的,如m
cout<<"n="<<n<<endl;
//n=3 说明:bind对于预先绑定的函数参数是通过值传递的,如n
A a;
//f5的类型为 function<void(int, int)>
auto f5 = std::bind(&A::fun_3, a,placeholders::_1,placeholders::_2); //使用auto关键字
f5(10,20);
//调用a.fun_3(10,20),print: k=10,m=20
std::function<void(int,int)> fc =
std::bind(&A::fun_3, a,std::placeholders::_1,std::placeholders::_2);
fc(10,20);
//调用a.fun_3(10,20) print: k=10,m=20
return 0;
}
总而言之, bind使用较为复杂, 还是推荐使用Lambda表达式来解决同类问题
Lambda表达式:
- lambda表达式可以理解为匿名的内联函数
- 与一般函数对象相同的部分: 返回类型, 参数列表, 和一个函数体
- 与一般函数不同的部分: 其可以定义在其他函数的内部, 如main()中
lambda的标准形式:
[capture list] (paramenter list) -> returnType { function body }
- capture list 捕获列表:
为lambda所在函数中定义的局部变量的列表
通常情况下为空 - 其他部分的内容和普通的函数一样
- 简单的lambda表达式定义可以忽略参数列表, 箭头和返回值类型, 但是永远包含捕获列表和函数体
此时编译器会根据函数体中的return内容来推断返回类型 - lambda的参数列表中不能有默认参数
即不能有缺省值
例如:
auto ff=[](int a, int b) ->int
{
return a+b;
};
lambda表达式的简略定义模式:
//简略的定义模式:
auto ff=[]{
cout<<"Hello lambda"<<endl;
};
//完整的定义模式:
auto ff=[]()->void{
cout<<"Hello lambda"<<endl;
};
捕获列表:
lambda表达式可在capture list捕获列表中提供一个以逗号分隔的名字列表, 用于捕获其所在的函数中定义的变量:
int x=0;
int y=42;
auto ff=[x, &y]
{
cout<<“x:”<<x<<endl;
cout<<“y:”<<y<<endl;
y++;
};
x=y=77;
ff();
ff();
输出结果:
X=0
Y=77
X=0
Y=78
本例中, capture list为x,&y, 捕获了本地的同名变量, 其中x是外部的值拷贝, y为外部变量的引用, 其具体操作和函数传参类似
其中还可以将capture list中的标识符换成[=,&y]或[&,x]
但是这里头有坑, 现在暂时还是写标识符为妙
实际使用:
int main(){
vector<int> vec{1,3,5,2,6,9};
int value=3;
int cnt=count_if(vec.begin(),vec.end(),
[=](int i) {return i>value; } );
cout<<cnt<<endl;
return 0;
}
//其中, count_if的功能等价于:
template <class InputIterator, class UnaryPredicate>
typename iterator_traits<InputIterator>::difference_type
count_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
typename iterator_traits<InputIterator>::difference_type ret = 0;
while (first!=last) {
if (pred(*first)) ++ret; //如果满足条件, 则计数器++
++first;
}
return ret;
}
本例中, lambda表达式捕获了本地变量value, 而count_if 向其传递一个参数, 编译器推断lambda返回值类型为bool, 所以实现了统计区间内值大于3的元素的个数
STL常用算法:
首先, 再次强调, 如果容器中提供了功能相同的算法, 优先使用容器中的算法!
非修改类算法:
查找算法:
无序容器查找算法
本部分算法时间复杂度为o(n)
- find()、find_if()
- adjacent_find():查找连续的2个相同的元素
- find_first_of():同时位于两个区间的首个元素
- search():查找匹配的子序列
- find_end():search的逆序版本
- search_n():查找连续多个子序列的首个子序列
- min_element()
- max_element()
- find_if_not() :查找不符合条件的元素
- minmax_element():返回最大和最小值的pair
- all_of():是否所有元素都符合条件
- any_of():是否任意元素符合条件
- none_of():是否任意元素都不符合条件
有序容器查找算法:
- binary_search():折半查找,对数时间复杂度
- lower_bound()、upper_bound()、equal_range()可确定指定元素的区间范围
统计计数类算法:
-
accumulate():
累计计算(累加、累积) -
count()、count_if():
对指定区间按照元素计数count统计指定区间等于某个值的元素次数
count_if统计指定区间符合条件(函数对象)的元素次数
比较类算法:
相同容器类型的比较:
- 直接重载operator==, operator<运算符即可
不同容器类型的比较:
- 2个迭代器区间,逐个元素顺序比较
- equal():所有对应元素相同,返回true
- mismatch():返回两个区间首个不匹配元素的迭代器
- lexicographical_compare():第1个区间所有元素按照“字典顺序”小于第2个区间对应元素的值,返回true
遍历算法:
这里主要讲for_each()
//模板定义:
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function fn);
//功能等价:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function fn)
{
while (first!=last) {
fn (*first);
++first;
}
return fn; // or, since C++11: return move(fn);
}
实际上就是遍历区间内的所有元素, 并使用回调函数Function fn
例程:
int main()
{
map<int, int> myMap;
myMap.insert(make_pair(4, 40));
myMap.insert(make_pair(5, 50));
myMap.insert(make_pair(6, 60));
myMap.insert(make_pair(7, 70));
myMap.insert(make_pair(8, 80));
for_each(myMap.begin(), myMap.end(), &printPair);
return 0;
}
输出结果:
4->40
5->50
6->60
7->70
8->80
例程, 使用lambda表达式, 功能与之前的相同:
int main()
{
map<int, int> myMap;
for_each(myMap.begin(), myMap.end(),
[](const pair<int,int>& p) {
cout<<p.first<<“->”<<p.second<<endl;}
);
return 0;
}
输出结果:
4->40
5->50
6->60
7->70
8->80
修改类算法:
- 修改类算法从1个区间拷贝数据到另一个区间、移除元素、逆序元素等
- 都有源区间和目标区间的概念,从源区间读取数据,写入或修改目标区间
且源区间和目标区间可以是相同的,以实现就地修改 - 对于map、multimap、set、multiset这些关联容器,不作为目标容器区间
transform()算法:
- transform()遍历指定的源区间,针对每个元素,调用传入的函数对象,产生新的元素并写入目标区间。
- 如果将源区间和目标区间设置为相同,则就地修改目标
//模板定义:
///unary operation(1)
template <class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator transform (InputIterator first1, InputIterator last1,
OutputIterator result, UnaryOperation op);
///binary operation(2)
template <class InputIterator1, class InputIterator2,
class OutputIterator, class BinaryOperation>
OutputIterator transform (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, OutputIterator result,
BinaryOperation binary_op);
//功能等价:
template <class InputIterator, class OutputIterator, class UnaryOperator>
OutputIterator transform (InputIterator first1, InputIterator last1,
OutputIterator result, UnaryOperator op)
{
while (first1 != last1) {
*result = op(*first1); // or: *result=binary_op(*first1,*first2++);
++result; ++first1; //实际上就是将回调函数的返回值赋给目标区间的元素
}
return result;
}
- InputIterator first1, InputIterator last1
输入的区间的迭代器 - OutputIterator result 或 InputIterator2 first2, OutputIterator result
输出的目标区间的起始迭代器
或是目标区间的首尾迭代器 - UnaryOperator op
执行一元操作的可调用对象
例程:
int main()
{
vector<int> myVector; ……
for (auto i : myVector) cout<<i<<endl;
transform(myVector.begin(), myVector.end(), myVector.begin(), [](int i){return i+100;} );
for (auto i : myVector) cout<<i<<endl;
return 0;
}
copy() 算法:
- copy()算法从源区间拷贝元素到目标区间
两个区间不能相同,但可以交叉 - copy不是插入元素,只是将源区间元素覆盖目标区间的对应元素
//模板定义:
template <class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last,
OutputIterator result);
//功能等价:
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = *first; //执行的就是覆盖操作
++result; ++first;
}
return result;
}
例程:
int main(){
vector<int> vec1, vec2;
vec2.resize(vec1.size());
//将vec1的数据拷贝到vec2中
copy(vec1.begin(), vec1.end(),
vec2.begin());
for (auto i : vec2) cout<<i<<endl;
return 0;
}
copy_if() 算法:
- 功能和copy()相似, 但是其接受一个可调用对象, 并根据其返回值来拷贝元素:
//模板定义:
template <class InputIterator, class OutputIterator, class UnaryPredicate>
OutputIterator copy_if (InputIterator first, InputIterator last,
OutputIterator result, UnaryPredicate pred);
//功能等价:
template <class InputIterator, class OutputIterator, class UnaryPredicate>
OutputIterator copy_if (InputIterator first, InputIterator last,
OutputIterator result, UnaryPredicate pred){
while (first!=last) {
if (pred(*first)) {
*result = *first; //如果回调函数返回的是true, 则执行copy
++result;
}
++first;
}
return result;
}
剩余的一些不重要的算法暂时忽略, 重点关注大篇幅的算法
移动算法:
略
替换算法:
略
replace_if()算法:
//模板定义:
template <class ForwardIterator, class UnaryPredicate, class T>
void replace_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred, const T& new_value );
//功能等价:
template < class ForwardIterator, class UnaryPredicate, class T >
void replace_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred, const T& new_value)
{
while (first!=last) { //如果回调函数返回true, 则用new_value替代相应的值
if (pred(*first)) *first=new_value;
++first;
}
}
如果回调函数返回true, 则用new_value替代相应的值
移除算法:
remove_if()算法:
//模板定义:
template <class ForwardIterator, class UnaryPredicate>
ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred);
//功能等价:
template <class ForwardIterator, class UnaryPredicate>
ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred)
{
ForwardIterator result = first;
while (first!=last) {
if (!pred(*first)) { //如果回调函数返回false,则移除相应位置的
*result = std::move(*first);
++result;
}
++first;
}
return result;
}
同样, 如果回调函数返回true, 则用new_value替代相应的值
排重算法:
略
反转算法:
略
排序类算法:
基础排序和合并:
sort() 算法:
//模板定义:
//default (1)
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
//custom (2)
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
这玩意还是很熟悉的, 不进行相应的拓展了
<补充>:
Lambda表达式在sort中的使用:
void sortByName(void){
std::sort(pCommodities, pCommodities+commodityNum,
[](CommodityInfo &c1, CommodityInfo &c2)->bool{
return c1.id<c2.id;
});
return ;
}
需要注意的是, sort使用可调用对象comp时, 传入的都是类型的引用, 所以这里需要设置为引用才能使用
merge()算法:
- 将两个有序的序列合并为一个有序的序列
//模板定义:
//default (1)
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
//custom (2)
template <class InputIterator1, class InputIterator2,
class OutputIterator, class Compare>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, Compare comp);
- first1 & last1 first2 & last2
为需要合并的两个有序区间 - result
为存放结果的容器 - comapre
为比较函数(可略写,默认为合并为一个升序序列)
堆排序:
略
其他排序:
略
集合算法:
-
includes():判断一个区间是否另一个区间的子集,顺序无关,要求2个区间已序
-
set_union()、set_intersection()、set_difference()、 set_symmetric_difference():
实现标准的并、交、差和异或集合运算,要求2个区间已序
并:存在于任意一个区间
交:存在于两个区间,公共部分
差:存在于第一个区间,但不存在于第二个区间
异或:只存在于一个区间,排除两个区间共存的 -
不能用关联容器保存集合运算结果
迭代器适配器:
STL提供的基本迭代器类型:
- iterator
- const_iterator
STL还提供了基于基本迭代器之上的适配器,以实现特殊的遍历功能
- reverse_iterator:
逆向迭代器 - ostream_iterator、istream_iterator:
输入输出流迭代器,将输入输出流当做容器 - insert_iterator:
插入迭代器
nputIterator2 first2, InputIterator2 last2,
OutputIterator result);
//custom (2)
template <class InputIterator1, class InputIterator2,
class OutputIterator, class Compare>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, Compare comp);
- first1 & last1 first2 & last2
为需要合并的两个有序区间
- result
为存放结果的容器
- comapre
为比较函数(可略写,默认为合并为一个升序序列)
### 堆排序:
略
### 其他排序:
略
## 集合算法:
- includes():判断一个区间是否另一个区间的子集,顺序无关,要求2个区间已序
- set_union()、set_intersection()、set_difference()、 set_symmetric_difference():
实现标准的并、交、差和异或集合运算,要求2个区间已序
并:存在于任意一个区间
交:存在于两个区间,公共部分
差:存在于第一个区间,但不存在于第二个区间
异或:只存在于一个区间,排除两个区间共存的
- 不能用关联容器保存集合运算结果
# 迭代器适配器:
STL提供的基本迭代器类型:
- iterator
- const_iterator
STL还提供了基于基本迭代器之上的适配器,以实现特殊的遍历功能
- reverse_iterator:
逆向迭代器
- ostream_iterator、istream_iterator:
输入输出流迭代器,将输入输出流当做容器
- insert_iterator:
插入迭代器