C++ STL标准库容器 概览
前言
本文对C++中的STL标准库容器进行概览,作为笔者平时的学习笔记,以兹备忘。同时,本文作为一个目录,接下来对常用容器,比如vector
,map
等的 具体介绍的博文将会由本文进行索引。
C++的标准容器库中提供了一系列的容器模版,可以作为日常工作生产中的数据结构使用,以此减少了程序员很多去造轮子的工作量。容器(container),顾名思义,是一种按照某种特性,用于储存某种类型数据的一种数据结构,其中通常还包含了若干对这种数据结构进行运算的算法,比如出栈,入栈,排列等等,C++将整个数据容器视为一种数据容器类,方便程序员的使用。通常来说,C++标准容器可以分为以下四大类型:
- 序列容器(Sequence containers)
- 序列容器适配器 (Sequence container adapters)
- 关联容器 (Associative containers)
- 无序关联容器 (Unordered associative containers)
我们分别简单介绍这四大类型容器中的常用的容器模版。
序列容器
序列容器以一种线性的方式去储存相同类型的数据类型的一系列数据。包括:
array
, 静态的,连续数组,类似于C语言中的数组。vector
,动态的,连续数组,其长度可以随着插入或者移除的元素而变化。forward_list
,单向链表list
,双向链表deque
,一种双端队列,元素可以在该队列的头部或者尾部插入和弹出。(不能在中间插入,只能在两端插入)
序列容器适配器
容器适配器是一种容器类的特殊类型。他们自己并不是完全的容器类,其依赖于对其他容器类型(比如vector
,list
,deque
)进行一层更高层级的语法包裹,封装起来(wrapper),以达到其设计的功能。容器适配器可以对潜在的容器类型进行压缩,限制该被包裹的容器的某些用户接口行为。
我们以std:stack
为例子,栈结构的特点是LIFO,也就是Last In First Out,因此必须限制某些用户接口,只能让容器数据从某个方向有规律有顺序地弹出或者插入。我们并不需要重新对这个stack数据结构进行编码,只需要在某些已经实现了特定功能的数据结构,比如deque
中,进行限制接口即可了。我们会发现,std:stack
的声明如:
template<
class T,
class Container = std::deque<T>
> class stack;
注意到这个stack
容器默认情况下是对std:deque<T>
的一种封装,包裹。你也可以指定特定的容器,取代这里的deque
。
标准容器中的容器适配器有:
stack
,提供LIFO的数据结构queue
,提供了FIFO的数据结构priority_queue
,提供了一个优先队列,其允许在该队列中以常数时间复杂度去检索最大的元素(默认情况下)
关联容器
关联容器提供了一种排序后的数据结构,配合对keys
的检索,可以提供一个快速的检索,时间复杂度为。
在STL的关联容器中,其按照检索的keys
,可分为两大类:A. 每个元素都只有唯一的key
; B. 可以用相同的key
检索多个元素。
- 唯一
key
:
set
,唯一key
检索,根据key
的某些特性进行排序(比如数值大小,首字母顺序等)map
,key-value
对的集合,也是根据key
的某些特性进行排序(比如数值大小,首字母顺序等)
-> 这两者通常都是通过红黑树进行实现的。
- 同一个
key
检索多个元素:multiset
,类似于set
,只不过可能有重复的key
multimap
,类似于map
,只不过可能有重复key
我们以set
为例,观察下其模版原型:
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;
我们发现,我们可以指定其排列的规则,默认是std:less
。
无序关联容器
无序关联容器,类似于关联容器,不过其是无序的,不需要对元素进行排序,通常根据hash进行索引。在最差的情况下,其时间复杂度是,不过大部分时候都远比线性操作要快得多,可以视为,即是在常数时间内就可以对元素进行检索。无序关联容器有:
key
是唯一的:unordered_set
,类似于set
,只不过是无序的。unordered_map
,类似于map
,只不过是无序的。
key
不唯一:
unordered_multiset
,类似于multiset
,只不过是无序的。unordered_multimap
,类似于multimap
,只不过是无序的。
以unordered_set
的模版原型为例子,有:
template<
class Key,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>
> class unordered_set;
Reference
[1]. https://embeddedartistry.com/blog/2017/08/02/an-overview-of-c-stl-containers/