zoukankan      html  css  js  c++  java
  • STL 源码剖析之四:序列式容器

    stl里的容器按元素在容器内的排列方式,可以分为序列式和关联式两种。

    所谓序列式容器,其中的元素时可序的,即元素集合呈线性关系。

    C++本身提供了一个序列式容器array,stl提供了vector,list,deque,stack,queue,priority_queue等序列容器。其中stack和queue由于只是将deque盖头换面,在技术上称之为适配器。

    1、Vector

    vector的元素存储和访问方式和array很相似,唯一的不同就在于弹性。array是静态空间,一旦配置了就不能改变;vector是动态空间,随着元素的增多或减少,其配置空间的大小可以动态改变。

    vector的迭代器:由于vector使用的是连续线性的空间,所以其迭代器实际就是原生指针,这显然是个Random Access Iterator。

    空间配置策略:从效率考虑,当插入元素的时候,如果配置的空间不足,则扩充空间至当前的两倍,如果任然不足则扩充至所需空间。 插入或删除元素时,涉及元素的拷贝和初始化。

    2、List

    list是一个双向链表,每次插入或删除一个元素,就分配或释放一个元素的空间;所以list对空间的控制十分精确,而且任何位置的插入或删除需要的时间都是常数。list和vector是两种最常用的容器,什么时候选用哪种容器,视元素的多寡、元素的构造复杂度(是否有trivial copy ctor,assignment opt)以及元素存取的行为特性。

    list的迭代器:list不能再以原生指针作为迭代器,而需要定义特定的iterator类。list迭代器是一种Bidirectional Iterator,支持单步的前进或后退操作。list迭代器有一个重要特点,就是插入操作不会造成原有迭代器的实效,这对vector是不成立的。

    list的结构:list不仅是一个双向链表,而且是一个带头结点的环状双向链表。

    list的sort方法:list不能使用stl提供的通用sort算法,因为sort算法只接受Random Access Iterator,所以提供了自己的sort方法。sort方法的实现在另一篇中有描述。

    3、Deque

    vector是单向开口的连续线性空间,deque则是一种双向开口的连续线性空间。所谓双向开口,意思是可以在头尾分别做元素的的安插和删除操作;vector当然也可以在头尾两端做动作,但是其头部动作效率奇差。deque和vector最大的差异在于:deque允许在常数时间内对两端进行元素的安插或移除操作;deque没有所谓容量的概念,因为它是以分段的连续空间组合而成,随时可以增加一段空间拼接起来,不存在像vector那样“因空间不足而分配一块更大的空间然后复制元素”问题。

    deque的迭代器:deque提供random access iterator,但并不是原生指标。其实现的复杂度也很大,这也影响到相关算法的效率。所以如非必要,应该尽量使用vector而不是deque。对的确进行排序时,可以先将元素复制到一个vector,排序后再复制回deque。

    deque的存储结构:deque采用的是一种分段连续空间存储结构,采用一个map(不是stl中的map)来管理这些空间段。每个空间段的大小是固定的,当有新元素加入而空间不足时,就分配一个新的空间段。当空间段的个数增加时,可能需要分配一个更大的map。 deque的这种结构,是的其迭代器上的操作可能需要跨越空间段,因而具有相当的复杂度。

    4、Stack

    stack是一种先进后出的数据结构,只可以在顶端进行元素操作。如果有某种双向开口的数据结构,将其接口改变,符合“先进后出”的特性,就可以形成一个stack:deque和list都是这样的结构。

    因此stack的实现非常简单,它以某种现有的容器作为存储的实现,定义新的接口。这种容器被称为container adapter。

    template <class T, class Sequence=Deque<T> >

    class stack

    {

    ...

    }

    如上所示,stack默认使用deque来实现,你也可以使用list: stack<int, list<int> >;

    stack不支持对元素的遍历,因此没有迭代器。

    5、Queue

    queue是一宗先进先出的数据结构,它的实现方案和stack基本一样。也是属于container adapter一类。可以基于deque和list。

    queue没有迭代器。 

    6、heap

    heap并不是stl中的一种容器,它实际是以vector作为完全二叉树的存储结构,再加上一些heap算法。它是priority_queue的背后英雄。

    stl定义了一些heap操作的算法:包括建堆,push_heap,pop_heap,sort_heap等,基本上和《算法导论》堆排序一章介绍的一致。

    7、Priority Queue

    priority queue是一种拥有权值概念的queue,加入的元素按权值大小排列。priority_queue也是container adapter,它以vector为存储结构,再以heap算法进行处理:priority_queue的元素存放在一个vector当中,按元素权值排列成一个heap。

    priority queue同样没有迭代器。

  • 相关阅读:
    [LeetCode]题解(python):007-Reverse Integer
    [LeetCode]题解(python):006-ZigZag Conversion
    [LeetCode]题解:005-Longest Palindromic Substring优化
    [LeetCode]题解(python):005-Longest Palindromic Substring
    [LeetCode]题解(python):003-Longest Substring Without Repeating Characters
    [LeetCode]题解(python):002-Add Two Numbers
    [LeetCode]题解(python):001-Two-Sum
    【BZOJ1005】【HNOI2008】明明的烦恼
    BZOJ平推计划
    【BZOJ1004】【HNOI20008】cards
  • 原文地址:https://www.cnblogs.com/longhuihu/p/10423373.html
Copyright © 2011-2022 走看看