- vector<T>:随机访问编程序列,即:访问复杂度为O(1),对序列末尾的插入和删除均是分摊常量;(数组表示)
- deque<T>:随机访问边长序列,对序列开头和末尾的插入和删除操作均是分摊常量的;(两级数组结构实现)
- list<T>:(双向链表)对变长序列的线性时间访问;对序列中任意位置的插入和删除操作时间复杂度为O(1);(双向链表实现)
- set<Key>:支持唯一的键(每个键只出现一次),并可快速检索键;
- multi<Key>:支持可重复的键(同一个键可出现多次),可快速检索键key
- map<Key,T>:键值对,支持唯一的键;可通过键快速检索其对应的类型为T的值;(用find(Key)数据成员实现)
- multimap<Key,T>:键值对,支持可重复的键;可通过键快速检索其对应的类型为T的值;
- find(iterator1 , iterator2, search_content):若找到,返回第一个出现search_content的位置,否则返回容器某位元素后面一个元素的迭代器;
例:
vector<char> vec1 = make<vector<char> >("C++");
find(vec1.begin|(),vec1.end(),'C');
- 调用形式
merge( first1 , last1 , first2 , last2, result );
(1) 迭代器first1和last1表示一个输入序列的起始和终止位置,元素类型为T;
(2)迭代器first2和last2表示另一个输入序列的起始和终止位置,元素类型为T;
(3)两个输入序列均为升序排列;
(4)result表示合并序列存放的起始位置;注意:结果容器所有元素均升序排列;若前面两个容器中元素均未升序排列,合并后的result容器非升序排列;三个容器不一定是同一类容器,可以属于不同类别,如:分别为list,char[] , deque容器,但元素类型必须为T;
2 #include <iostream>
3 #include <deque>
4 #include <list>
5 #include <algorithm>
6 #include "string.h"
7 #include "stdlib.h"
8 using namespace std;
9
10 template<typename container>
11 container make( const char source[]);
12
13 int main()
14 {
15 char s[]="acd";(升序)
16 int len = strlen(s);
17 list<char> list1 = make< list<char> >("befghijklmnopqrstuvwxy");(升序)
18 deque<char> d(26,'x');
19
20 merge(&s[0],&s[len] , list1.begin() , list1.end(),d.begin());
23 std::cout<<"result ok"<<std::endl;
24 return 0;
25 }
26
27
28 template<typename container>
29 container make( const char source[])
30 {
31 return container( &source[0] , &source[strlen(source)]);
32 }
1.迭代器分类
- 输入迭代器:支持!=,*,++,==,但是对于*操作,只能从容器中读取数据,而不能向其中写入数据;
- 输出迭代器:支持!=,*,++,==,但是对于*操作,不能从容器中读取数据,只能向其中写入数据
- 前向迭代器:支持==,!= , *,++操作;
- 双向迭代器:支持==,!= , *,++,--操作;
- 随机访问迭代器:支持==,!= , *,++,--,+=,-=,+,-,<,>,<=,>=操作
- 类属函数accumulate:accumulate(first,last,init),把init和从first到last指向的值进行累加并返回累加得到的和;
- 函数对象:一个实体,可以不带参数,也可以带有一个以上的参数,并能够从中获得一个值或改变程序的状态,除了普通函数,另一类函数对象可以是类或结构的对象,且在其定义中重载了函数调用运算符。
2 #include <vector>
3 #include <algorithm>
4 #include <numeric> //for accumulate
5
6 using namespace std;
7
8 class multi{
9 public:
10 //function call overload
11 int operator()(int x , int y ) const
12 {
13 return x*y;
14 }
15 };
16
17 int main()
18 {
19 int x[5]={1,2,3,4,5};
20 vector<int> vec1(&x[0],&x[5]);
22 int result = accumulate(vec1.begin() , vec1.end() , 1, multi());
23 std::cout<<"result is:"<<result<<std::endl;
24 }
- 在类multi中定义函数调用运算符operator(),就定义了一种可以作为函数参数的对象,可以像使用函数一样使用该对象;multi()使用编译器提供的默认构造函数;该对象没有响应的内存,只有函数定义;
- 函数对象的优势
(1)以类的形式定义函数对象,可以携带更多额外信息,某些类属算法或容器将会用到这类信息;
(2)更加通用、高效
- 适配器reverse_iterator:将某种类型的迭代器变成一种新的迭代器,但保持其功能不变,将其遍历的方向翻转过来。(使用场景:如用find函数查找某个元素在容器中最后出现的位置;浮点数累加,若元素升序排列,舍入误差通常会小一些,否则,以降序顺序排列时,与累加和相比,非常小的数值对于累加和几乎不起任何作用,因此可用reverse_iterator和accumulate实现降序序列浮点数累加,结果精确些)
- 注:STL每种容器都定义了reverse_iterator,以及返回这种类型迭代器的rbegin和rend成员函数
- 栈适配器:将序列容器变换到先进后出的栈接口中;
- 队列适配器:将序列容器变换到先入先出队列中;
- 优先级队列:将序列容器变换到优先级队列中,由一个比较参数来控制元素访问顺序。
- 函数适配器:
(1)取反器(negator):对判定函数对象(返回值为bool类型)的结果进行取反;
(2)绑定器(binder):将二元函数的一个参数与某个特定的值绑定,从而将二元函数编程一元函数。
(3)函数指针适配器:从函数指针得到函数对象。