前言
Standard Template Library (STL)提供了四个部分,算法,容器,函数和迭代器。这里容器做一些说明总结,便于查看。具体的函数用法可以查看各自对应的链接。
有三类容器 - 序列容器,关联容器和无序关联容器,此外还有容器适配器提供一些常用的数据结构。
序列容器
序列容器实现了可以顺序地进行访问的数据结构。
array(C++11) static contiguous array
静态连续数组
vector dynamic contiguous array
向量,动态连续数组
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)
1、占据一块连续的内存空间;顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素
2、内部实现是通过管理了一个指针,只是当内存空间不够时,会重新分配一块更大的内存空间,通常是将容量扩大一倍;容器使用一个内存分配器对象来动态地处理它的存储需求。
3、支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。操供了在序列末尾相对快速地添加/删除元素的操作。vector对尾部操作很方便,对头部或者插入都需要O(n)的时间复杂度
用vector存储自定义类对象时,自定义类对象须满足:
a、有可供调用的无参构造函数(默认的或自定义的);
b、有可用的拷贝赋值函数(默认的或自定义的)
不同于map(map有find方法),vector本身是没有find这一方法,其find是依靠algorithm来实现的
-----
vector<int>::iterator it = find(vec.begin(), vec.end(), 6);
if (it != vec.end())
cout<<*it<<endl;
else
cout<<"can not find"<<endl;
————————————————
版权声明:本文为CSDN博主「test1280」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/test1280/java/article/details/65937779
deque double-ended queue
相对于向量,双端队列唯一的区别就是首端和尾端同样都是开放的
因此它同时提供在首尾两端增删元素的接口
首端增删: push_front/pop_front
尾端增删: push_back/pop_back
双端队列的内存开销和时间性能上略逊于向量
forward_list singly-linked list
单向列表
list doubly-linked list
双向列表
非连续存储结构,具有双链表结构,每个元素维护一对前向和后向指针,因此支持前向/后向遍历。
支持高效的随机插入/删除操作,但随机访问效率低下,且由于需要额外维护指针,开销也比较大。
迭代器只能使用++--操作,不能用+n -n,因为元素不是物理相连的
适用情况
vector V.S. list V.S. deque:
a、若需要随机访问操作,则选择vector;
b、若已经知道需要存储元素的数目, 则选择vector;
c、若需要随机插入/删除(不仅仅在两端),则选择list
d、只有需要在首端进行插入/删除操作的时候,才选择deque,否则都选择vector。
e、若既需要随机插入/删除,又需要随机访问,则需要在vector与list间做个折中。
f、当要存储的是大型负责类对象时,list要优于vector;当然这时候也可以用vector来存储指向对象的指针,同样会取得较高的效率,但是指针的维护非常容易出错,因此不推荐使用。
关联容器Associative containers
关联容器提供一些可以快速索引(O(log n) 复杂度)的数据结构
set, multiset, map, multimap 是一种非线性的树结构,具体的说采用的是一种比较高效的特殊的平衡检索二叉树—— 红黑树结构。
set collection of unique keys, sorted by keys
map collection of key-value pairs, sorted by keys, keys are unique
每个元素都是key/value pair(键值对),其中key是排序准则的基准。每个key只能出现一次,不允许重复。map可被视为一种关联式数组,即”索引可为任意类型”的数组。
不同于map(map有find方法),vector本身是没有find这一方法,其find是依靠algorithm来实现的
multiset collection of keys, sorted by keys
multimap collection of key-value pairs, sorted by keys
与map的区别:元素可以重复,即multimap允许有相同的key。
关联容器特点
关联容器的特点是明显的,相对于顺序容器,有以下几个主要特点:
1, 其内部实现是采用非线性的二叉树结构,具体的说是红黑树的结构原理实现的;
2, set 和map 保证了元素的唯一性,mulset 和mulmap 扩展了这一属性,可以允许元素不唯一;
3, 元素是有序的集合,默认在插入的时候按升序排列。
基于以上特点,
1, 关联容器对元素的插入和删除操作比vector 要快,因为vector 是顺序存储,而关联容器是链式存储;比list 要慢,是因为即使它们同是链式结构,但list 是线性的,而关联容器是二叉树结构,其改变一个元素涉及到其它元素的变动比list 要多,并且它是排序的,每次插入和删除都需要对元素重新排序;
2, 关联容器对元素的检索操作比vector 慢,但是比list 要快很多。vector 是顺序的连续存储,当然是比不上的,但相对链式的list 要快很多是因为list 是逐个搜索,它搜索的时间是跟容器的大小成正比,而关联容器 查找的复杂度基本是Log(N) ,比如如果有1000 个记录,最多查找10 次,1,000,000 个记录,最多查找20 次。容器越大,关联容器相对list 的优越性就越能体现;
3, 在使用上set 区别于vector,deque,list 的最大特点就是set 是内部排序的,这在查询上虽然逊色于vector ,但是却大大的强于list 。
4, 在使用上map 的功能是不可取代的,它保存了“键- 值”关系的数据,而这种键值关系采用了类数组的方式。数组是用数字类型的下标来索引元素的位置,而map 是用字符型关键字来索引元素的位置。在使用上map 也提供了一种类数组操作的方式,即它可以通过下标来检索数据,这是其他容器做不到的,当然也包括set 。(STL 中只有vector 和map 可以通过类数组的方式操作元素,即如同ele[1] 方式
无序关联容器
无序关联容器提供一些无序的数据结构(hashed),能够快速索引(O(1) amortized, O(n) worst-case 复杂度)
unordered_set collection of unique keys, hashed by keys
无序集合容器(unordered_set)是一个存储唯一(unique,即无重复)的关联容器(Associative container),容器中的元素无特别的秩序关系,该容器允许基于值的快速元素检索,同时也支持正向迭代。
在一个unordered_set内部,元素不会按任何顺序排序,而是通过元素值的hash值将元素分组放置到各个槽(Bucker,也可以译为“桶”),这样就能通过元素值快速访问各个对应的元素(均摊耗时为O(1))。
原型中的Key代表要存储的类型,而hash<Key>也就是你的hash函数,equal_to<Key>用来判断两个元素是否相等,allocator<Key>是内存的分配策略
c++对非常规类型使用unordered_set<>的话必须要手写哈希函数
unordered_map collection of key-value pairs, hashed by keys, keys are unique
unordered_multiset collection of keys, hashed by keys
unordered_multimap collection of key-value pairs, hashed by keys
容器适配器 Container adaptors
容器适配器提供一些顺序容器的接口,来实现一些其他的数据结构。
stack adapts a container to provide stack (LIFO data structure)
栈的特点是后进先出,所以它关联的基本容器可以是任意一种顺序容器,因为这些容器类型结构都可以提供栈的操作有求,它们都提供了push_back、pop_back和back操作。
queue adapts a container to provide queue (FIFO data structure)
队列queue的特点是先进先出,适配器要求其关联的基础容器必须提供pop_front操作,因此其不能建立在vector容器上;
priority_queue adapts a container to provide priority queue 优先队列
最高优先级元素总是第一个出列
元素的比较规则默认按元素的值由大到小排列,也可以重载“<"操作符来重新定义比较规则。
优先级队列则是基于vector实现的。当然,我们也可以指定自己的实现方式。但是由于数据结构的关系,我们也不能随意指定。
优先级队列priority_queue 适配器要求提供随机访问功能,因此不能建立在list 容器上。
参考:
https://en.wikipedia.org/wiki/Standard_Template_Library#Containers
https://en.cppreference.com/w/cpp/container
https://blog.csdn.net/u010398493/article/details/52298744