STL

1 篇文章 0 订阅

容器分类

顺序容器:vector / list / deque / forward_list(C11)
关联容器: set / multiset / map / multimap
无序关联容器(C11): unordered_set / unordered_multiset / unordered_map / unordered_multimap
容器适配器: stack / queue / priority_queue
还可以根据结构来分类,线性和非线性

顺序容器

vector

特点:
1.vector的本质是数组,但是优于数组,数组的大小固定,vector的大小可以动态扩展。
2.拥有一段连续的内存空间,并且起始地址不变,支持随机存取,即 [] 操作符。
3.对头部和中间进行插入删除元素操作需要移动内存,插入位置越靠后,移动的元素越少,效率越高。
4.对尾元素操作最快,此时一般不需要移动内存

动态扩容机制:
当容器的capacity不足时,会进行动态扩容。
执行步骤:分配新空间-复制元素-释放原空间
因此适用vector的最佳场景是知道数据的规模,在初始化vector的时候,设置好capacity容量,就不会触发动态扩容,不会影响性能。
reverse(int)可以设置预留的容器的空间

优缺点及适用场景:
优点:支持随机访问,即 [] 操作和 .at(),所以查询效率高。
缺点:当向其头部或中部插入或删除元素时,为了保持原本的相对次序,插入或删除点之后的所有元素都必须移动,所以插入的效率比较低。
适用于对象简单,变化较小,并且频繁随机访问的场景

操作时间复杂度
push_backO(1)
pop_backO(1)
insertO(n)
eraseO(n)
访问[]O(1)

list

特点:
1.本质是双向链表,内存空间不连续,元素存放在堆中
2.不支持随机访问,插入删除效率高
3.每分配一个元素都会从内存中分配,每删除一个元素都会释放它占用的内存

适用场景:
适用于频繁插入删除,不经常随机访问的场景

操作时间复杂度
push_frontO(1)
push_backO(1)
pop_frontO(1)
pop_backO(1)
insertO(1)
eraseO(1)
访问O(n)

deque

结构图
特点:
1.按照页或者块来分配存储器,每页包含固定数目的元素
2.支持随机储存
3.头尾删除插入元素效率高

适用场景:
适用于既要频繁随机存取,又要关心两端数据的插入与删除的场景

操作时间复杂度
push_frontO(1)
push_backO(1)
pop_frontO(1)
pop_backO(1)
insertO(n)
eraseO(n)
访问O(1)

关联容器

关联容器的特点比较相似,因此统一进行记录。

特点:
1.都是由红黑树实现,有序
2.set的元素不能重复,multiset/multimap是可以一对多(一个key对应多个value)
3.增删改查时间复杂度都近似于O(logn)

红黑树与平衡二叉树(AVL树):
平衡树的优点:
同种元素序列情况下的深度最小的二叉排序树。这可以减少二叉树元素查找的深度,从而提升平均查找效率。

AVL树:
(1 )左子树和右子树的深度之差的绝对值不超过1;
(2)左子树和右子树也是平衡二叉树。
执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保存平衡,而因为旋转非常耗时,由此我们可以知道AVL树适合用于插入与删除次数比较少,但查找多的情况

红黑树:
通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因此,红黑树是一中弱平衡二叉树
相对于要求严格的AVL树来说,它的旋转次数少,插入最多两次旋转,删除最多三次旋转,所以对于搜索,插入,删除操作较多的情况下,我们就用红黑树

折中选择红黑树作为关联容器的底层数据结构。

无序关联容器

特点:
1.都是基于哈希表实现,无序
2.查找效率O(1),耗时在构建hash表和解决hash冲突,维护hash表上面

hash表:
根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表
hash冲突的解决办法:
1.开放地址法,发生hash碰撞的时候,顺序查下一个位置是否碰撞,直到查完全表或者找到不碰撞的位置,进行使用
2.再次hash法
3.拉链法,一个数组中挂着多个链表的指针,hash碰撞,就把新结点挂在hash值的列表上
4.建立公共溢出区,将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表

容器适配器

stack:
在这里插入图片描述

1.仅允许在一端进行插入(push)和删除(pop)运算。这一端被称为栈顶,相对地,把另一端称为栈底。
2.插入:向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素
3.删除:从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素
4.最后入栈的一组数据可以最先被取出,这种行为也被叫做LIFO:Last In First Out,即后进先出

stack的基本操作:
1.入栈:如s.push(x)
2.出栈:如 s.pop().注意:出栈操作只是删除栈顶的元素,并不返回该元素
3.访问栈顶:如s.top()
4.判断栈空:如s.empty().当栈空时返回true
5.访问栈中的元素个数,如s.size()

queue:
在这里插入图片描述
1.在一端插入,另一端删除
2.FIFO(先进先出)

queue的基本操作:
1.入队,如例:q.push(x); 将x 接到队列的末端。
2.出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
3.访问队首元素,如例:q.front(),即最早被压入队列的元素。
4.访问队尾元素,如例:q.back(),即最后被压入队列的元素。
5.判断队列空,如例:q.empty(),当队列空时,返回true。
6.访问队列中的元素个数,如例:q.size()

priority_queue:
1.默认是最大堆,堆顶是最大的元素
2.queue相当于是先进去的优先级最大的一个priority_queue,因此priority_queue是有序的。

函数声明:priority_queue< type, container, function >

这三个参数,后面两个可以省略,第一个不可以。
type:数据类型
container:实现优先队列的底层容器
function:元素之间的比较方式
第二个参数忽略,默认是使用vector存储,第三个比较函数忽略,默认是最大堆
基本操作同queue

截止到此,第一篇文章关于STL的总结结束了,继续努力总结~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值