C++STL泛型算法

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:
	插入迭代器

发布了17 篇原创文章 · 获赞 7 · 访问量 1346

猜你喜欢

转载自blog.csdn.net/qq_42683011/article/details/104058759
今日推荐