综述
全称:Standard Template Library,标准模板库
-
迭代器是沟通算法和容器的桥梁,容器相当于数据结构,算法根据容器提供的迭代器进行操作 -> 数据结构有了配套的操作
容器
容器更像一个类
Vector
特点:
- 拥有一段连续的内存空间,因此它能非常好的
支持随机访问
,即 [] 操作符和 .at(),随机访问快。(优点) - 当向其头部或中间插入或删除元素时,为了
保持原本的相对次序
,插入或删除点之后的所有元素都必须移动,所以插入或删除的效率比较低
。(缺点) - 在后面插入删除元素最快,此时一般不需要移动内存。(优点)
- 总结:相当于可拓展的数组(
动态数组
),随机访问快,在头部和中间插入或删除效率低,但在尾部插入或删除效率高。
- 拥有一段连续的内存空间,因此它能非常好的
操作:
1.
push_back
在数组的最后添加一个数据2.pop_back 去掉数组的最后一个数据
3.
at
得到编号位置的数据4.begin 得到数组头的指针
5.end 得到数组的最后一个单元+1的指针
6.front 得到数组头的引用
7.back 得到数组的最后一个单元的引用
8.max_size 得到vector最大可以是多大
9.capacity 当前vector分配的大小
10.
size
当前使用数据的大小11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
12.reserve 改变当前vecotr所分配空间的大小
13.erase 删除指针指向的数据项
14.
clear
清空当前的vector15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)
16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)
17.empty 判断vector是否为空
18.swap 与另一个vector交换数据
特性:
- 在动态扩容上,vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是
以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来
,然后才开始在原内容之后构造新元素,并释放原空间。因此, 对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了
。
- 在动态扩容上,vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是
deque
deque(double-ended queue)是双向开口的连续内存空间(动态将多个连续空间通过指针数组接合在一起),随时可以增加一段新的空间。deque 的最大任务就是
在这些分段的连续空间上,维护其整体连续的假象,并提供随机存取的接口
。特点
一旦要在 deque 的头部和尾部增加新空间,便配置一段定量连续空间,串在整个 deque 的头部或尾部,因此不论在头部或尾部插入元素都十分迅速。 (优点)
在中间部分安插元素则比较费时,因为必须移动其它元素。(缺点)
deque 是 list 和 vector 的折中方案。兼有 list 的优点,也有 vector 随机访问效率高的优点。
总结:支持随机访问,但效率没有 vector 高,在头部和尾部插入或删除效率高,但在中间插入或删除效率低。
set
- 每个元素最多只出现一次,并且 set 中的元素已经从小到大排好序
- 特点
- 使用红黑树实现,其内部元素依据其值自动排序,每个元素值只能出现一次,不允许重复。
- 每次插入值的时候,都需要调整红黑树,效率有一定影响。(缺点)
- map 和 set 的插入或删除效率比用其他序列容器高,因为对于关联容器来说,不需要做内存拷贝和内存移动。(优点)
- 总结:由红黑树实现,其内部元素依据其值自动排序,每个元素值只能出现一次,不允许重复,且插入和删除效率比用其他序列容器高。
list
List 由双向链表(doubly linked list)实现而成,元素存放在堆中,每个元素都是放在一块内存中。没有空间预留习惯,所以每分配一个元素都会从内存中分配,每删除一个元素都会释放它占用的内存。
特点
- 内存空间可以是不连续的,通过指针来进行数据的访问,这个特点使得它的随机存取变得非常没有效率,因此它没有提供 [] 操作符的重载。(缺点)
- 由于链表的特点,在任意位置的插入和删除效率都较高。(优点)
- 只支持首尾两个元素的直接存取,想获取其他元素(访问时间一样),则需要遍历链表。(缺点)
- 总结:不支持随机访问,在任意位置的插入和删除效率都较高。
map
map 由红黑树实现,其元素都是 “键值/实值”
所形成的一个对组(key/value pairs)。
map 主要用于资料一对一映射的情况,map 内部自建一颗红黑树,这颗树具有对数据自动排序的功能,所以在 map 内部所有的数据都是有序的。比如一个班级中,每个学生的学号跟他的姓名就存在着一对一映射的关系。
特点
- 每个元素都有一个键,且只能出现一次,不允许重复。
- 根据 key 值快速查找记录,查找的复杂度基本是 O(logN),如果有 1000 个记录,二分查找最多查找 10次(1024)。(优点)
- 每次插入值的时候,都需要调整红黑树,效率有一定影响。(缺点)
- 增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。(优点)
- 对于迭代器来说,可以修改实值,而不能修改 key。
- 总结:元素为键值对,key 和 value 可以是
任意你需要的类型
,每个元素都有一个键,且只能出现一次,不允许重复,根据 key 快速查找记录。
适用场景
适用于需要存储一个数据字典,并要求方便地根据key找value的场景。
iterator
迭代器类似指针,指向容器中的某个元素,用->(如果容器中的元素是pair,可以用it->first与it->second访问第一个和第二个值)或者*(元素为一个值)访问指向的元素
容器适配器 stack、queue 和 priority_queue
没有
迭代器。容器适配器有一些成员函数,可以用来对元素进行访问。分类:
- 正向:容器类名<>::iterator 迭代器名;
- 反向:容器类名<>::reverse_iterator 迭代器名;
- 常量正向:容器类名<>::const_iterator 迭代器名;
- 常量反向:容器类名<>::const_reverse_iterator 迭代器名;
迭代器都可以进行
++
操作。反向迭代器和正向迭代器的区别在于:对正向迭代器进行
++
操作时,迭代器会指向容器中的后一个元素;而对反向迭代器进行
++
操作时,迭代器会指向容器中的前一个元素。使用正向/反向迭代器写for循环迭代时,要写it != container.end()/rend()而不是<=,因为反向迭代器的++是反向的,都这么写美观整齐