【C++】STL相关容器的对比

目录

一、序列容器(vector、list、deque)

1、vector(向量容器)

2、list(链表容器)

3、deque(双端队列容器)

 二、关联容器(set、multiset、map、 multimap)

1、set(集合)/multiset(多重集合)

2、 map(映射)/multimap(多重映射)

 3、unordered_set(无序集合)/unordered_multiset (无序多重集合)       unordered_map( 无序映射)/unordered_multimap(无序多重映射)

三、总结


一、序列容器(vector、list、deque)

1、vector(向量容器)

类似C语言中的动态数组,在堆中以一段连续内存空间存储

特性:

1)若是该容器内存空间不够的时候,系统会另外开辟 一个更大的内存空间,进行内存拷贝操作,将原先内存空间的数据进行“搬家”,并对“旧家”进行销毁。值得注意的是:其每次扩容的空间为原来的两倍。

2)跟数组特性一致,拥有一段连续内存空间,能够使用 [ ] 操作符 进行很好地索引,即随机存取。但是对于增删操作不够友好,每次增删需要进行内存块拷贝移动,大大影响代码效率。
增加:push_back(val) O(1)         insert(it, val) O(n)
删除:pop_back() O(1)          erase(it) O(n)
查询:iterator operator[] find O(n)           binary_search O(logn)

特别方法:
resize(10):开辟空间,还放数据
reserve(10) :只开辟空间,不放数据。初始化vector空间,提高vector的使用效率
 0 - 1 -2 - 4 - 8 -16

2、list(链表容器)

类似双向链表,在堆中以不连续内存空间存储,通过指针进行数据访问

特性:跟链表特性一致,对于增删操作很友好,因为每次需要分配元素内存空间时会从内存中分配,删除元素也会释放其的内存空间,代码增删执行效率很高。


增加:push_front(val) O(1)    push_back(val) O(1)   insert(it, val) O(1)
删除:pop_front() O(1)          pop_back() O(1)          erase(it) O(1)
查询:iterator find O(n)

特别方法:把链表的一个或者几个节点摘下来,直接接到另一个链表当中
splice
list1 list2
list1.splice(list1.begin(), list2, list2.begin());
意思:把list2容器的list2.begin()这个位置的节点摘下来,放入list1容器的list1.begin()起始位置

list1.splice(list1.begin(), list2, list2.begin(), list2.end());
意思:把list2容器的list2.begin()到list2.end()这个位置的所有节点摘下来,放入list1容器的list1.begin()起始位置 

3、deque(双端队列容器)

deque容器为一个给定类型的元素进行线性处理,像向量一样,它能够快速地随机访问任一个元素,并且能够高效地插入和删除容器的尾部元素。但它又与vector不同,deque支持高效插入和删除容器的头部元素,因此也叫做双端队列。

特性:
底层:动态开辟的二维数组,第一维会进行2倍的扩容,第二维是固定大小的数组,内存分段连续的

deque是由一段一段的定量连续空间构成。一旦有必要在deque的前端或尾端增加新空间,便配置一段定量连续空间,串接在整个deque的头端或尾端。deque的最大任务,便是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的接口。避开了“重新配置、复制、释放”的轮回,代价则是复杂的迭代器结构。

deque采用一块所谓的map(不是STL的map容器)作为主控。

map是一小块连续空间,其中每个元素(此处称为一个节点,node)都是指针,指向另一段(较大的)连续线性空间,称为缓冲区。

缓冲区才是deque的储存空间主体。

增加:push_front(val) O(1)          push_back(val)O(1)           insert(it, val) O(n)
删除:pop_front() O(1)                pop_back() O(1)                 erase(it) O(n)
查询:iterator operator[] find O(n)                    binary_search O(logn)

 二、关联容器(set、multiset、map、 multimap)

1、set(集合)/multiset(多重集合)

set 是按照特定顺序存储唯一元素的容器。multiset允许元素重复而set不允许。

特性:

set/multiset 的底层数据结构都是 红黑树,一种高效的平衡搜索二叉树。

set :键和值都相等(模板里只有一个参数,键和值合在一起);键值唯一;元素默认按键值升序

multiset :键和值都相等;键值不唯一;元素默认按键值升序

set 容器中每一个元素就是二叉树的每一个节点,对于set容器的插入删除操作,效率都比较高。原因是因为二叉树的删除插入元素并不需要进行内存拷贝和内存移动,只是改变了指针的指向。

对 set 进行插入删除操作都不会引起iterator的失效,因为迭代器相当于一个指针指向每一个二叉树的节点,对set的插入删除并不会改变原有内存中节点的改变, 但是vector的插入删除操作一般会发生内存移动和内存拷贝,所以会发生迭代器的失效。

set容器的检索速度很快,因为采用二分查找的方法(O(logn)) 。

增加: insert({key,value}) operator[] O(logn)
删除: erase(key) O(1)
查询: iterator自己搜索-线性搜索-O(n)          find(key)成员方法 O(logn)

2、 map(映射)/multimap(多重映射)

map按照特定顺序存储,按键值对方式存储元素,即(key,value);
Multimap 的特性以及用法与 map 基本相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制 RB-tree 的 insert_equal() 而非 insert_unique。 

特性:

map/multimap的底层数据结构都是 红黑树,一种高效的平衡二叉搜索树。

map :键和值分开(模板里有两个参数,前面是键、后面是值);键值唯一;元素默认按键值升序

multiset :键和值分开;键值不唯一;元素默认按键值升序

 3、unordered_set(无序集合)/unordered_multiset (无序多重集合)
       unordered_map( 无序映射)/unordered_multimap(无序多重映射)

特性:
底层数据结构:链式哈希表

哈希表是根据关键码值而进行直接访问的数据结构,通过相应的哈希函数(也称散列函数)处理关键字得到相应的关键码值,关键码值对应着一个特定位置,用该位置来存取相应的信息,这样就能以较快的速度获取关键字的信息。

增删查 O(1)
增加: insert({key,value}) operator[] O(1)
删除: erase(key) O(1)
查询: iterator自己搜索-线性搜索-O(n) find(key)成员方法 O(1)

三、总结

常见STL容器对比图
容器类型 序列容器 关联容器
  vector list deque set multiset map multimap
容器名称 向量容器 链表容器 双向队列容器 集合 多重集合 映射 多重映射
底层数据结构 连续存储的数组(二倍扩容) 双向循环链表 连续或分段连续存储数组 红黑树
头文件引用 #include<vector> #include<list> #include<deque> #include<set> #include<set> #include<map> #include<map>
操作元素的方式 下标运算符[ ]、迭代器 迭代器 下标运算符、迭代器 迭代器
插入删除操作迭代器是否失效 插入和删除元素都会失效

插入:迭代器不会失效

删除:指向被删除结点的迭代器失效

插入:任何元素迭代器都会失效

删除:头部和尾部元素,指向别删结点迭代器失效,删除中间元素,所有迭代器失效

插入:迭代器不会失效

删除:指向被删除结点的迭代器失效


 

猜你喜欢

转载自blog.csdn.net/Jacky_Feng/article/details/115016884