STL的各个容器?

STL的各个容器?

序列式容器

vecor,动态数组模型,它维护的是一个连续线性空间。

vector的扩容:并不是在原空间之后接着开辟新空间(因为无法保证之后有可供配置的空间),而是每次再分配原大小两倍的内存空间,这是一个配置新空间(malloc),拷贝移动数据(memcpy),释放旧空间(free)的大工程,时间成本很高。因此,对vector的任何操作,一旦引起控件重新配置,指向原vector的所有迭代器就都失效了。
vector维护的是一个连续线性空间,因此vector迭代器具备普通指针的功能,支持随机存取。

list

相对于vector的连续线性空间,list,与向量(vector)相比, 它允许快速的插入和删除,且每次插入或删除一个元素,就配置或释放一个元素空间。
list不再能够像vector那样以普通指针作为迭代器,因为其节点不保证在储存空间中连续存在。list迭代器必须有能力指向list的节点,并有能力进行正确的递增、递减、取值、成员存取等操作。
list是一个带有头结点循环双向链表。所以它只需要一个指针,便可以完整实现整个链表。迭代器必须具备前移、后移的能力,所以list提供的是双向迭代器

deque

可以在头尾两端分别做元素的插入和删除操作,它是动态地以分段连续空间组合而成。
deque是由一段一段的连续空间构成。一旦有必要在deque的前端或尾端增加新空间,便配置一段定量的连续空间,串接在整个deque的头端或尾端。deque的最大任务,便是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的接口。避开了“重新配置、复制、释放”的轮回,代价则是复杂的迭代器架构。

关联式容器

每项数据(元素)包含一个键值(key)和一个实值(value),标准的STL关联式容器分为set(集合)和map(映射类)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表)。这些容器的底层机制均以RB-tree完成(红黑树)。

set和mutilset

set:其键值对的键和值相同,那么set更像普通的二叉树即结点是键值和实值。
set的键值不允许相同,所以set的value值也没有相同的。而这也是mutilset和set唯一的不同,mutilset可以有相同的键值。
set是基于红黑树的所以其中的元素会自动排序。
思考:
(1)为何map和set的插入删除效率比用其他序列容器高?
因为对于关联容器来说,不需要做内存拷贝和内存移动。set容器内所有元素都是以节点的方式来存储,其节点结构和链表差不多,指向父节点和子节点。(用节点表示二叉树结构)
因此插入的时候只需要稍做变换,把节点的指针指向新的节点就可以了。删除的时候类似,稍做变换后把指向删除节点的指针指向其他节点也OK了。这里的一切操作就是指针换来换去,和内存移动没有关系。
(2)对set进行增删操作后,迭代器iterator如何变化?
set的迭代器本质上是const_iterator,这是因为RB-tree的结构依赖于数据的组织,如果允许通过iterator改变set元素值,会严重破坏RB-tree结构。
iterator这里就相当于指向节点的指针,内存没有变,指针就没有失效,只是指向的内容变化了。进行增删操作后,只影响本身的迭代器,对其它迭代器无影响。

map和mutilmap

map是映射之意,即用键值(key)映射实值数据(value)。
对比set,map的关联特效更加明显,但类似set,map也不允许有相同的键值,要想有相同键值可用mutilmap。

容器适配器

基于deque的顺序容器适配器stack、queue、priority_queue。

stack

是一种后进先出(First In Last Out,FILO)的数据结构,它只有一个出口。stack允许新增元素、移除元素、取得最顶端元素,不允许随机访问。底层结构为deque,对deque封闭头端开口。

queue

queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口。queue允许新增元素、移除元素、从最底端加入元素、取得最顶端元素。底层结构为deque,对deque封闭其底端的出口和前端的入口。

priority_queue

为优先级队列,它允许用户为队列中存储的元素设置优先级。这种队列不是直接将新元素放置在队列尾部,而是放置在比它优先级低的元素前面,即提供了一种插队策略。

猜你喜欢

转载自blog.csdn.net/baidu_37964071/article/details/81410658