这篇文章最早发布于关门2000的博客(www.gscience.cc)中。原文章为C++标准库中的容器,转载请注明
这篇文章参考于cppreference.com。在这篇文章中我们将介绍每种容器的特点,并不会去介绍详细的使用方法。
顺序容器:
array
array( 数组)是一种最简单的标准库容器,定义于头文件<array>中:template<
class T,
std::size_t N
> struct array;
array的功能基本与普通的C数组,性能也是如此,只不过拥有了一些C++标准容器的特性例如查询大小、复制、迭代等。
vector与deque
vector(容器)中的内存是连续的,所以我们除了可以利用迭代器之外,还可以通过指针的偏移来访问其中的元素。vector定义于头文件<vector>中:template<
class T,
class Allocator = std::allocator<T>
> class vector;
vector会在需要的时候动自动调整占用的内存的大小,与静态的array相比,vector占用的内存会更多,这一设计是为了降低重新分配内存的频率。我们可以通过capacity()来查询已分配的内存,通过shrink_to_fit()来归还已经分配的空闲的内存。我们可以随意向vector的任何位置添加、删除元素,但是只有在结尾删除元素的速度是最快的。同时如果对vector的大小有个预估,可以通过reserve()函数来为vector分配内存。
vector 上常见操作的复杂度(效率)如下:
- 随机访问 - 常数 O(1)
- 在尾部增删元素 - 平摊(amortized)常数 O(1)
- 增删元素 - 至 vector 尾部的线性距离 O(n)
提示:请不要试图使用vector<bool>,他会造成很严重的性能问题,甚至在新版的编译器中已经无法编译。与vector相反,deque(双向队列)其中的数据并不是连续储存的。deque允许在头部和尾部快速插入、删除元素。他定义在头文件<deque>中:
template<
class T,
class Allocator = std::allocator<T>
> class deque;
与vector类似,deque也会自动扩容。但是扩容deque的成本更低,因为deque不需要保证元素的连续性。同样,deque也是支持迭代器的。同时,向deque中插入元素不会使原有的指向元素的指针实效。
deque上常见操作的复杂性(效率)如下:
- 随机访问 - 常数O(1)
- 在结尾或开头插入或移除元素 - 摊销不变O(1)
- 插入或移除元素 - 线性O(n)
list与forward_list
list( 列表)支持任意位置的快速插入和删除,但是作为代价,他并不支持随机访问。list通常实现为双向的链表,定义于头文件<list>中:template<
class T,
class Allocator = std::allocator<T>
> class list;
与list相比,forward_list(
单向列表)只支持单向迭代,但其拥有更高的空间利用率。forward_list定义于头文件<forward_list>中:
template<
class T,
class Allocator = std::allocator<T>
> class forward_list;
关联容器:
set与multiset
set是一个关联型容器,不支持随机访问。定义在头文件<set>中:template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;
set(
集合)中包含不重复、类型Key的元素。相反的,在multiset(
多重集合)中的元素是可以重复的,multiset也定义于头文件<set>中:
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class multiset;
提示:无论是set还是multiset,都可以通过类型为Compare的比较函数来实现排序的。若遇到相等元素则他们的顺序就是插入时的顺序且不会改变。
map与multimap
map(映射)
是一个有序关联容器,不支持随机访问。定义在头文件<map>中:
template<
class Key,
class T,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, T> >
> class map;
在map中,包含具有唯一键的键值对。键通过比较函数Compare来排序,通常被现为红黑树。如果需要一个键对应多个元素,就需要使用multimap(
多重映射)。multimap定义于头文件<map>中:
template<
class Key,
class T,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, T> >
> class multimap;
提示:请尽量不要去遍历map和multimap,他们的设计决定了遍历的速度会很慢。
unordered_set,unordered_multiset和unordered_map
unordered_set(无序集合)是一个关联型容器,定义于头文件<unordered_set>中:
template<
class Key,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>
> class unordered_set;
unordered_multiset(无序多重集合)是一个关联型容器,定义于头文件<unordered_multiset>中:
template<
class Key,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>
> class unordered_multiset;
unordered_map(无序映射)是一个关联型容器,定义于头文件<unordered_map>中:
template<
class Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;
unordered_multimap(无序多重映射)是一个关联型容器,定义于头文件<unordered_multimap>中:
提示:以上四种无序容器通常都是用哈希表实现的,搜索,插入和去除具有平摊的常数时间复杂度,但是作为代价其内存占用会很高。