当前位置:网站首页>【STL】顺序容器之deque用法总结
【STL】顺序容器之deque用法总结
2022-06-23 05:57:00 【舒泱】
一、基本原理
vector是单向开口的连续线性空间,在头部操作效率奇差,无法被接受。deque则是一种双向开口的连续线性空间,可以在头尾两端分别做元素的插入和删除操作。
deque和vector的最大差异,一是在于deque允许于常数时间内对其头部进行元素的插入和删除操作,认识在于deque没有所谓容量(capacity)的概念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。也就是说,在deque中不存在像vector那样“因旧空间不足而重新配置一块更大的空间,然后赋值元素,释放旧空间”的事情。
deque也支持随机访问,你或许会觉得deque的实现复杂度和vector差不多,实际上deque的实现代码量远比vector或list都多得多。
如图,deque采用一小块连续空间作为主控,主控中的每个元素都是指针,指向另一段较大的连续线性空间,称为缓冲区,缓冲区是deque的存储空间主体。deque由一段一段的定量连续空间构成,为了维持整体连续的假象,deque数据结构的设计和迭代器的前进后退等操作都颇为繁琐,它的迭代器并不是普通指针。

二、用法
以下都以容器deque中的元素为int为例,若要保存其他类型的元素,将int换成其他类型即可。
初始化
| 创建一维队列的方法 | deque<类型名> 队列名; |
|---|---|
| deque<int> d1; | 创建一个名为d1的空队列,d1中的元素类型为int |
| deque<int> d1(100,7); | d1中的元素为100个7 |
| deque<int> d1{1,2,3,……}; | 元素为1,2,3,……的d1 |
| deque<int> d2(d1); | 队列d2中包含和队列d1一样的元素 |
| deque<int> d2=d1; | 队列d2中包含和队列d1一样的元素 |
访问元素
| 访问元素 | |
|---|---|
| d1[n] | 访问下标为n的那个元素 |
| d1.at(n); | 访问下标为n的那个元素 |
| d1.front(); | 访问d1的队首元素 |
| d1.back(); | 访问d1的队尾元素 |
| *iter | 访问迭代器iter指向的元素 |
| 获取迭代器 | |
|---|---|
| d1.begin(); | 获取指向d1队首元素的迭代器 |
| d1.end(); | 获取指向d1队尾元素的后一个位置的迭代器 |
| d1.rbegin(); | 获取指向d1队首元素的前一个位置的迭代器 |
| d1.rend(); | 获取指向d1队尾元素的迭代器 |
| d1.cbegin(); d1.cend(); | 含义同上,但获取到的是const_iterator |
| d1.crbegin(); d1.crend(); | 含义同上,但获取到的是const_iterator |
遍历容器
1、普通for语句
for (int i = 0; i < d1.size(); ++i) {
cout << d1[i] << endl; // 输出当前元素并换行
}
使用迭代器
for (deque<int>::iterator iter = d1.begin(); iter != d1.end();++iter) {
cout << *iter << endl; // 输出当前元素并换行
}
2、范围for语句
for (auto it : d1) {
cout << it << endl; // 输出当前元素并换行
}
添加与删除元素
| 添加 | |
|---|---|
| d1.push_front(a); | 在d1队首添加一个元素a |
| d1.emplace_front(a); | 在d1队首添加一个元素a |
| d1.push_back(a); | 在d1队尾添加一个元素a |
| d1.emplace_back(a); | 在d1队尾添加一个元素a |
| d1.insert(iter,a); | 迭代器iter指向的元素之前添加一个元素a |
| d1.insert(iter,n,a); | 迭代器iter指向的元素之前添加 n 个元素a |
| d1.insert(iter,{a,b,c}); | 迭代器iter指向的元素之前添加大括号内的所有元素,这里添加的元素是a、b、c |
| 删除 | |
|---|---|
| d1.pop_front(); | 在d1队首删除一个元素 |
| d1.pop_back(); | 在d1队尾删除一个元素 |
| d1.erase(iter); | 删除迭代器iter指向的元素 |
| d1.erase(iter1,iter2); | 删除迭代器iter1和ter2指向的范围中元素 |
| d1.clear(); | 删除d1中的所有元素 |
替换元素
| swap、assign | |
|---|---|
| d1=d2; | 将d1中的元素替换为d2 |
| d1.swap(d2); | 交换d1和d2的元素,swap通常比从d2向d1拷贝元素要快得多 |
| swap(d1,d2); | 交换d1和d2的元素,swap通常比从d2向d1拷贝元素要快得多 |
| d1={1,2,3,……}; | 将d1中的元素替换为初始化列表中的元素1,2,3,…… |
| d1.assign(iter1,iter2); | 将d1中的元素替换为迭代器iter1和iter2所指范围中的元素。迭代器iter1、iter2不能指向d1中的元素 |
| d1.assign({1,2,3,……}); | 将d1中的元素替换为初始化列表中的元素1,2,3,…… |
| d1.assign(7, 1); | 将d1中的元素替换为7个1(仅为举例,换成别的也行) |
deque的大小
| d1.szie(); | 获得d1实际上使用的空间的大小 |
|---|---|
| d1.empty(); | 若d1为空返回值为true,否则返回值为false |
| d1.maxsize() | 可保存的最大元素的数目 |
| d1.shrink_to_fit(); | 退回容器不需要的内存空间,调用该函数不保证一定退回内存空间 |
| d1.resize(n) | 调整d1的大小为n个元素,若n<d1.size(),多余的元素会被丢弃。若要添加新元素,新元素会被默认初始化(比如0) |
| d1.resize(n,t) | 调整d1的大小为n个元素,任何添加的新元素值会被初始化为t |
查找、替换、排序、去重、求和
请使用C++标准库里的泛型算法(find、replace、sort、unique、accumulate……),标准库提供了100多个算法,这些算法适用于大多数容器。
三、时间复杂度
| 操作 | |
|---|---|
| 随机访问 | O(1) |
| 查找 | O(n) |
| 在队首或队尾添加元素 | 若不重新分配空间,O(1) |
| 在队首或队尾删除元素 | O(1) |
四、注意事项:下标越界、迭代器失效
下标越界
当你使用d1[n]访问队列元素时,如果n>=d1.size(),函数的行为是未定义的,编译器并不会帮你检查队列下标是否合法,保证下标合法是程序员的责任。
如果你使用d1.at(n)访问队列元素,如果下标n越界,at函数会跑出一个out_of_range异常。
迭代器失效
向容器中添加或删除元素都有可能会使容器的迭代器失效。
向容器添加元素后:
- (1) deque和string:若存储空间重新分配,则迭代器全部失效。若存储空间没有重新分配,则指向插入位置之前的元素的迭代器仍有效,之后的元素的迭代器将会失效。
- (2) deque:插入元素到除了首尾位置之外的任何位置,都会使迭代器、指针、引用失效。插入元素到首尾,迭代器会失效,指向原来元素的指针和引用仍有效。
- (3) list和forward_list:迭代器、指针、引用仍然有效。
在容器中删除一个元素后:
- (1) deque和string:指向被删除元素之前的迭代器、引用、指针仍有效。当我们删除元素时,尾后迭代器总是会失效。
- (2) deque:在首尾位置之外的任何位置删除元素,迭代器、指针、引用都会失效。如果删除的是尾元素,那么尾后迭代器失效,其他迭代器、引用、指针仍有效。如果删除的是首元素,迭代器、指针、引用仍有效。
- (3) list和forward_list:指向除删除元素外的其他元素的迭代器、指针、引用仍然有效。
边栏推荐
- 小白投资理财必看:图解基金买入与卖出规则
- 746. 使用最小花费爬楼梯-动态规划
- 页面嵌入iframe 点击浏览器后退问题
- Machine learning artifact scikit learn minimalist tutorial
- Open source to the world (Part 2): the power of open source from the evolution of database technology BDTC 2021
- 图解三次握手四次挥手,小白都能看懂
- Common setup modes (Abstract Factory & responsibility chain mode & observer mode)
- mysql 索引
- Phpstudy set 301 redirection
- Copy and paste of idea without escape
猜你喜欢

Programmers' real ideas | daily anecdotes

Copy and paste of idea without escape

Linux安装mysql8.0.25

光谱共焦的测量原理及厚度测量模式

haas506 2.0开发教程-hota(仅支持2.2以上版本)

How to view native IP

Sword finger offer 42 Maximum sum of successive subarrays

Easy EDA learning notes 09 esp32-wroom-32e module esp32-devkitc-v4 development board one click download circuit

cmder

图解三次握手四次挥手,小白都能看懂
随机推荐
Children's programming for comprehensively cultivating students' mental thinking
Easy EDA learning notes 09 esp32-wroom-32e module esp32-devkitc-v4 development board one click download circuit
【shell】Tree命令
Haas506 2.0 development tutorial - Advanced Component Library -modem Net (only supports versions above 2.2)
C# 获取DPI和真实分辨率的方式(可以解决一直是96的问题)
快速认识 WebAssembly
How to realize video call and live interaction in a small program when live broadcasting is so popular?
问题:访问组件中数据object(定义的数据)中属性也为object对象中的属性时,报错现象
回调函数详解
2.17 haas506 2.0开发教程-system(仅支持2.2以上版本)
mongodb 记录
VS2013 FFMPEG环境配置及常见错误处理
QT method of compiling projects using multithreading
Storage mode of data in memory (C language)
cmder
直播带货这么火,如何在小程序中实现视频通话及直播互动功能?
idea自动生成serialVersionUID
994. rotten oranges - non recursive method
常见设置模式(抽象工厂&责任链模式&观察者模式)
ssm + ftp +ueditor