STL库中的容器部分

序列化容器

1、vector
vector使用线性连续空间。增加新元素 (s) 时,如果超过当时的容量,则容量会扩充至两倍。如果两倍容量仍不足,就扩张至足够大的容量。容量的扩张必须经历「重新配置、元素搬移、释放原空间」等过程,工程浩大。
当我们以 push_back() 将新元素安插于 vector 尾端,该函式首先检查是否还有备用空间?如果有就直接在备用空间上建构元素,并调整迭代器 finish ,使 vector变大。如果没有备用空间了,就扩充空间(重新配置、搬移数据、释放原空间)
TIPS:所谓动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大空间,然后将原内容拷贝过来,然后才开始在原内容之后建构新元素,并释放原空间。因此,对 vector 的任何操作,一旦引起空间重新配置,指向原 vector 的所有迭代器就都失效了。这是程序员易犯的一个错误,务需小心。
2、list
相较于 vector 的连续线性空间, list 就显得复杂许多,它的好处是每次安插或删除一个元素,就配置或释放一个元素空间。因此, list 对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素安插或元素移除, list 永
远是常数时间。list 和 vector 是两个最常被使用的容器。什么时机下最适合使用哪一种容器,必须视元素的多寡、元素的构造复杂度(有无 non-trivial copy constructor, non-trivial
copy assignmen operator)、元素存取行为的特性而定。
list的数据结构
(首尾相连的双向链表)


List

SGI list 不仅是一个双向串行,而且还是一个环状双向串行。所以它只需要一个指标,便可以完整表现整个串行。只要
刻意在环状串行的尾端加上一个空白节点,便符合 STL规范之「前闭后开」区间。
list的迭代器
list 不再能够像 vector 一样以原生指标做为迭代器,因为其节点不保证在储存空间中连续存在。 list 迭代器必须有能力指向 list 的节点,并有能力做正确的递增、递减、取值、成员存取…等动作。所谓「 list 迭代器正确的递增、递减、取值、成员取用」动作是指,递增时指向下一个节点,递减时指向上一个节点,取值时取的是节点的资料值,成员取用时取用的是节点的成员。由于STL list 是一个双向串行(double linked-list),迭代器必须具备前移、后
移的能力。所以 list 提供的是Bidirectional Iterators。
deque
vector 是单向开口的连续线性空间, deque 则是一种双向开口的连续线性空间。所谓双向开口,意思是可以在头尾两端分别做元素的安插和删除动作.


deque

deque 和 vector 的差异:
deque 和 vector 的最大差异,一在于 deque 允许于常数时间内对起头端进行元素的安插或移除动作,二在于 deque 没有所谓容量( capacity )观念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。
换句话说,像 vector 那样「因旧空间不足而重新配置一块更大空间,然后复制元素,再释放旧空间」这样的事情在 deque 是不会发生的。也因此, deque 没有必要提供所谓的空间保留( reserve )功能。虽然 deque 也提供Ramdon Access Iterator,但它的迭代器并不是原生指标,其
复杂度和 vector 不可以道里计(稍后看到源码,你便知道),这当然在在影响了各个运算层面。因此,除非必要,我们应尽可能选择使用 vector 而非 deque 。对deque 进行的排序动作,为了最高效率,可将 deque 先完整复制到一个 vector身上,将 vector 排序后(利用 STL sort 算法),再复制回 deque 。deque 系由一段一段的定量连续空间构成。一旦有必要在 deque 的前端或尾端增加新空间,便配置一段定量连续空间,串接在整个 deque 的头端或尾端。 deque 的最大任务,便是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的界面。避开了「重新配置、复制、释放」的轮回,代价则是复杂的迭代器架构。
deque 采用一块所谓的map(注意,不是 STL 的 map 容器)做为主控。这里所谓map是一小块连续空间,其中每个元素(此处称为一个节点,node)都是指标,指向另一段(较大的)连续线性空间,称为缓冲区。缓冲区才是 deque 的储存空间主体。SGI STL允许我们指定缓冲区大小,默认值 0表示将使用 512 bytes缓冲区。
deque 除了维护一个先前说过的指向map的指标外,也维护 start, finish 两个迭代器,分别指向第一缓冲区的第一个元素和最后缓冲区的最后一个元素(的下一位置)。此外它当然也必须记住目前的map大小。因为一旦map所提供的节点不足,就必须重新配置更大的一块map。
stack
stack 是一种先进后出(First In Last Out,FILO)的数据结构。它只有一个出口, stack 允许新增元素、移除元素、取得最顶端元素。但除了最顶端外,没有任何其它方法可以存取 stack 的其它元素。换言之 stack 不允许有走访行为。
将元素推入 stack 的动作称为 push,将元素推出 stack 的动作称为pop。
以某种既有容器做为底部结构,将其接口改变,使符合「先进后出」的特性,形
成一个 stack ,是很容易做到的。 deque 是双向开口的数据结构,若以 deque 为底部结构并封闭其头端开口,便轻而易举地形成了一个 stack 。因此,SGI STL 便以 deque 做为预设情况下的 stack 底部结构, stack 的实作因而非常简单,源码十分简短,本处完整列出。由于 stack 系以底部容器完成其所有工作,而具有这种「修改某物接口,形成另一种风貌」之性质者,称为adapter(配接器),因此 STL stack 往往不被归类为 container(容器),而被归类为container adapter。

除了 deque 之外, list 也是双向开口的数据结构。上述 stack 源码中使用的底层容器的函式有 empty, size, back, push_back, pop_back ,凡此种种 list都具备。因此若以 list 为底部结构并封闭其头端开口,一样能够轻易形成一个stack 。
stack没有迭代器。
queue
queue 是一种先进先出(First In First Out,FIFO)的数据结构。它有两个出口, queue 允许新增元素、移除元素、从最底端加入元素、取得最顶端元素。但除了最底端可以加入、最顶端可以取出,没有任何其它方法可以存取queue的其它元素。换言之 queue 不允许有走访行为。将元素推入queue 的动作称为 push,将元素推出 queue 的动作称为pop。以某种既有容器为底部结构,将其接口改变,使符合「先进先出」的特性,形成一个 queue ,是很容易做到的。 deque 是双向开口的数据结构,若以 deque 为底部结构并封闭其底端的出口和前端的入口,便轻而易举地形成了一个 queue。
除了 deque 之外, list 也是双向开口的数据结构。上述 queue 源码中使用的底层容器的函式有 empty, size, back, push_back, pop_back ,凡此种种 list都具备。因此若以 list 为底部结构并封闭其头端开口,一样能够轻易形成一个
queue 。
由于 queue 系以底部容器完成其所有工作,而具有这种「修改某物接口,形成另
一种风貌」之性质者,称为adapter(配接器),因此 STL queue 往往不被归类
为 container(容器),而被归类为container adapter。
heap:
heap 并不归属于STL 容器组件,它是个幕后英雄,扮演 priority queue 的推手。顾名思义, priorityqueue 允许使用者以任何次序将任何元素推入容器内,但取出时一定是从优先权最高(也就是数值最高)之元素开始取。 binary max heap 正是具有这样的特性,适合做为 priority queue 的底层机制。
priority_queue
顾名思义, priority_queue 是一个拥有权值观念的 queue ,它允许加入新元素、
移除旧元素,审视元素值等功能。由于这是一个 queue ,所以只允许在底端加入
元素,并从顶端取出元素,除此之外别无其它存取元素的途径。
priority_queue 带有权值观念,其内的元素并非依照被推入的次序排列,而是自动依照元素的权值排列(通常权值以实值表示)。权值最高者,排在最前面。预设情况下 priority_queue 系利用一个 max-heap 完成,后者是一个以 vector表现的 complete binary tree(4.7 节)。max-heap 可以满足 priority_queue 所需要的「依权值高低自动递增排序」的特性。
priority_queue没有迭代器
priority_queue 的所有元素,进出都有一定的规则,只有 queue 顶端的元素(权值最高者),才有机会被外界取用。 priority_queue 不提供走访功能,也不提供迭代器。
slist:
STL list 是个双向串行(double linked list)。SGI STL 另提供了一个单向串行
(single linked list),名为 slist 。这个容器并不在标准规格之内,不过多做一
些剖析,多看多学一些实作技巧也不错,所以我把它纳入本书范围。
slist 和 list 的主要差别在于,前者的迭代器属于单向的 Forward Iterator,后
者的迭代器属于双向的Bidirectional Iterator。为此, slist 的功能自然也就受到
许多限制。不过,单向串行所耗用的空间更小,某些动作更快,不失为另一种选
择。
slist 和 list 共同具有的一个相同特色是,它们的安插(insert)、移除(erase)、
接合(splice)等动作并不会造成原有的迭代器失效(当然啦,指向被移除元素的
那个迭代器,在移除动作发生之后肯定是会失效的)。
注意,根据STL的习惯,安插动作会将新元素安插于指定位置之前,而非之后。然而做为一个单向串行, slist 没有任何方便的办法可以回头定出前一个位置,因此它必须从头找起。换句话说,除了 slist 起始处附近的区域之外,在其它位置上采用 insert 或 erase 操作函式,都是不智之举。这便是 slist 相较于 list之下的大缺点。为此, slist 特别提供了 insert_after() 和 erase_after() 供弹性运用。基于同样的(效率)考虑, slist 不提供 push_back() ,只提供 push_front() 。因此slist 的元素次序会和元素安插进来的次序相反。

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

推荐阅读更多精彩内容

  • 标签(空格分隔): STL 运用STL,可以充分利用该库的设计,让我为简单而直接的问题设计出简单而直接的解决方案,...
    认真学计算机阅读 1,462评论 0 10
  • STL部分 1.STL为什么广泛被使用 C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vec...
    杰伦哎呦哎呦阅读 4,291评论 0 9
  • 容器的概念所谓STL容器,即是将最常运用的一些数据结构(data structures)实现出来。容器是指容纳特定...
    饭饭H阅读 371评论 0 0
  • STL(标准模板库),是目前C++内置支持的library。它的底层利用了C++类模板和函数模板的机制,由三大部分...
    岁与禾阅读 38,876评论 3 133
  • C++ 标准模板库(STL) 作者:AceTan,转载请标明出处! 0x00 何为STL## STL(Standa...
    AceTan阅读 4,913评论 3 44