C++ STL 容器

前言

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容