文章目录
1 deque容器基本概念
作用:双端数组
,可在容器的头部和尾部插入或删除元素。
deque容器的迭代器:支持随机访问的迭代器,可跳跃式访问容器元素。
deque与vector区别:
总结:deque头插、头删快,查询/访问慢;vector头插、头删慢,查询/访问快。
(1)vector
容器属于单端数组
,头部插入或删除元素的效率低,需要移动所有元素,且数据量越大,效率越低。
deque
容器属于双端数组
,支持头部插入或删除元素,效率高于vector容器。
(2)vector
访问元素的速度快于deque
。
vector
内部采用连续的线性空间;
deque
内部采用中央控制器与数据缓冲区。当访问至当前缓冲区的末尾时,需通过中央控制器查找下一缓冲区的地址,再访问下一缓冲区的数据。
deque的内部工作原理(内部结构):
deque内部存在中央控制器
,记录与维护每段数据缓冲区
的内存地址,缓冲区中存储真实数据,保证可从容器的头部与尾部插入或删除元素。
deque的内部结构,保证使用deque类似于访问连续的内存空间,但实际是不连续的内存空间。
push_front()
:头插法插入数据。
pop_front()
:头删法删除数据。
push_back()
:尾插法插入数据。
pop_back()
:尾删法删除数据。
front()
:获取deque容器的第1个元素。
back()
:获取deque容器的最后1个元素。
begin()
:获取起始迭代器,指向容器中的第1个元素。
end()
:获取结束迭代器,指向容器中的最后1个元素的下一个位置。
2 deque构造函数
作用:创建deque容器。
注:使用deque容器时,需包含头文件
#include <deque>
。
函数原型:
(1)deque<T> deq;
:默认无参构造函数,采用类模板实现。
(2)deque(deq.begin(), deq.end());
:拷贝容器对象deq
的[begin(), end())
区间(左闭右开,包左不包右)的元素进行初始化。
(3)deque(n, elem);
:有参构造函数,使用n
个elem元素
进行初始化。
(4)deque(const deque &deq);
:拷贝构造函数,使用已有deque对象初始化新的对象。
注:当遍历
vector
或deque
容器的元素时:
若希望遍历过程中元素不被修改,可使用只读迭代器const_iterator
;
若将遍历功能封装成函数时,可将函数形参使用const
修饰。
tip:当遍历函数的形参使用const
修饰后,遍历访问时必须使用只读迭代器const_iterator
。
示例:deque构造函数
#include <iostream>
using namespace std;
#include <deque> //包含头文件
//函数模板:遍历deque容器的通用函数
template<typename T>
void printDeque(const deque<T> &deq) { //形参使用const,避免被修改
//形参使用const后,遍历时必须使用只读迭代器const_iterator
for (deque<T>::const_iterator it = deq.begin(); it != deq.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
/* 1.默认无参构造函数 */
deque<int> d1;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
d1.push_back(i);
}
//遍历
printDeque<int>(d1); //0 1 2 3 4
/* 2.有参构造,区间拷贝 */
//左闭右开区间的元素
deque<int> d2(d1.begin(), d1.end());
printDeque<int>(d2); //0 1 2 3 4
/* 3.n个elem元素赋值 */
//5个整型元素6
deque<int> v3(5, 6);
printDeque<int>(v3); //6 6 6 6 6
/* 4.拷贝构造函数 */
deque<int> v4(v3);
printDeque<int>(v4); //6 6 6 6 6
return 0;
}
3 deque赋值操作【operator=、assign()】
作用:通过重载赋值运算符operator=
和成员函数assign()
,对deque容器进行赋值。
函数原型:
(1)deque& operator=(const deque &deq);
:重载赋值运算符,使用目标deque容器,对当前deque容器赋值。
(2)assign(begin, end);
:拷贝目标deque容器中[begin(), end())
区间(左闭右开,包左不包右)的元素,对当前deque容器赋值。
(3)assign(n, elem);
:使用n
个elem元素
,对当前deque容器赋值。
示例:deque赋值操作
#include <iostream>
using namespace std;
#include <deque> //包含头文件
//函数模板:遍历deque容器的通用函数
template<typename T>
void printDeque(const deque<T>& deq) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
for (deque<T>::const_iterator it = deq.begin(); it != deq.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
deque<int> deq;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
deq.push_back(i);
}
//遍历
printDeque<int>(deq); //0 1 2 3 4
/* 1.重载运算符=赋值 */
deque<int> d1 = deq;
printDeque<int>(d1); //0 1 2 3 4
/* 2.assign()函数,区间拷贝 */
//左闭右开区间的元素
deque<int> d2;
d2.assign(deq.begin(), deq.end());
printDeque<int>(d2); //0 1 2 3 4
/* 3.assign()函数,n个elem元素赋值 */
deque<int> d3;
//5个整型元素6
d3.assign(5, 6);
printDeque<int>(d3); //6 6 6 6 6
return 0;
}
4 deque大小操作【size()、resize()】
作用:操作deque容器的大小(即元素个数)。
函数原型:
(1)empty();
:判断容器是否为空。
(2)size();
:获取容器的大小,即元素个数。
(3)resize(int num);
:重新指定容器的长度为num
。
若容器变长,则以默认值0
填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
(4)resize(int num, elem);
:重新指定容器的长度为num
。
若容器变长,则以指定值elem
填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
注:deque容器不存在容量的概念,即不存在
capacity()
成员函数。可随时开辟缓冲区存储数据。
示例:deque容的大小操作
#include <iostream>
using namespace std;
#include <deque> //包含头文件
//函数模板:遍历deque容器的通用函数
template<typename T>
void printDeque(const deque<T>& deq) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
for (deque<T>::const_iterator it = deq.begin(); it != deq.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
deque<int> deq;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
deq.push_back(i);
}
printDeque<int>(deq); //0 1 2 3 4
//empty():判断容器是否为空
cout << (deq.empty() ? "deq为空" : "deq不为空") << endl; //deq不为空
//size(); :获取容器的大小,即元素个数。
cout << "deq的大小/元素个数:" << deq.size() << endl; //5
//resize(int num);:重新指定容器的长度为num
//若容器变长,则以默认值0填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
deq.resize(10); //长度变大时,使用默认值0填充
printDeque<int>(deq); //0 1 2 3 4 0 0 0 0 0
deq.resize(3); //长度变小时,容器末尾超出新长度的元素被删除
printDeque<int>(deq); //0 1 2
//resize(int num, elem); :重新指定容器的长度为num。
//若容器变长,则以指定值elem填充新位置;若容器变短,则容器末尾超出新长度的元素被删除。
deq.resize(8, 6); //长度变大时,使用指定值6填充
printDeque<int>(deq); //0 1 2 6 6 6 6 6
return 0;
}
5 deque插入【push_front()、push_back()、insert()】和删除【pop_front()、pop_back()、erase()、clear()】
(1)deque容器插入元素:使用成员函数push_front()
、push_back(..)
、insert(..)
向deque容器插入元素。
函数原型:
①push_front(ele);
:头插法,向deque容器的头部插入元素ele
。
②push_back(ele);
:尾插法,向deque容器的尾部插入元素ele
。
③insert(const_iterator pos, ele);
:迭代器指向位置pos
插入元素ele
④insert(const_iterator pos, int n, ele);
:迭代器指向位置pos
插入n
个元素ele
。
⑤insert(const_iterator pos, const_iterator begin, const_iterator end);
:迭代器指向位置pos
插入[begin(), end())
区间(左闭右开,包左不包右)的元素,无返回值。
(2)deque容器删除元素:使用成员函数pop_front()
、pop_back(..)
、erase(..)
、clear(..)
删除deque容器中的元素。
函数原型:
①pop_front()
:头删法,删除deque容器头部的第1个元素。
②pop_back();
:尾删法,删除deque容器尾部的最后1个元素。
③erase(const_iterator pos);
:删除迭代器指向位置的元素。
④erase(const_iterator start, const_iterator end);
:删除迭代器指向位置[start, end)
区间的所有元素。
⑤clear();
:清空容器中的所有元素。
注1:清空容器的所有元素,
deq.clear();
等价于deq.erase(deq.begin(), deq.end());
。
注2:插入元素insert(..)
、删除元素erase(..)
均需要迭代器对象作为参数。
示例:deque容器插入和删除元素
#include <iostream>
using namespace std;
#include <deque> //包含头文件
//函数模板:遍历deque容器的通用函数
template<typename T>
void printDeque(const deque<T>& deq) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
for (deque<T>::const_iterator it = deq.begin(); it != deq.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//deque两端插入/删除数据
void func1() {
deque<int> deq;
//尾插法
deq.push_back(10);
deq.push_back(20);
//头插法
deq.push_front(2);
deq.push_front(1);
printDeque(deq); //1 2 10 20
//尾删法
deq.pop_back();
printDeque(deq); //1 2 10
//头删法
deq.pop_front();
printDeque(deq); //2 10
//清空元素
deq.clear();
printDeque(deq); //(空)
}
//deque指定位置插入/删除数据
void func2() {
deque<int> deq;
for (int i = 0; i < 5; i++) {
deq.push_back(i);
}
printDeque(deq); //0 1 2 3 4
//指定位置插入单个元素-insert()
deq.insert(deq.begin(), 10);
printDeque(deq); //10 0 1 2 3 4
//指定位置删除单个元素-erase()
deq.erase(deq.begin());
printDeque(deq); //0 1 2 3 4
//指定位置插入多个元素-insert()
deq.insert(deq.end(),3 ,10);
printDeque(deq); //0 1 2 3 4 10 10 10
//指定位置插入区间元素-insert()
deque<int> d;
d.insert(d.begin(), 3, -1);
printDeque(d); //-1 -1 -1
//在deq尾部插入d的[begin, end)区间元素
deq.insert(deq.end(), d.begin(), d.end());
printDeque(deq); //0 1 2 3 4 10 10 10 -1 -1 -1
//删除区间元素-erase
deq.erase(deq.begin(), deq.end());
printDeque(deq); //(空)
}
int main() {
//func1();
func2();
}
6 deque数据存取【operator[]、at()】
作用:通过重载赋值运算符operator[]
和成员函数at(int index)
,对deque容器的单个元素进行读(作为右值)或写(作为左值)。
函数原型:
(1)operator[](int index);
:重载运算符[],读写指定索引位置index
的元素。
(2)at(int index);
:成员函数,读写指定索引位置index
的元素。
(3)front();
:返回容器的第1个元素。
(4)back();
:返回容器的最后1个元素。
访问/遍历deque容器元素的方式:
①迭代器
②重载运算符[]
③成员函数at()
示例:deque读写元素
#include <iostream>
using namespace std;
#include <deque> //包含头文件
//函数模板:遍历deque容器的通用函数
template<typename T>
void printDeque(const deque<T>& deq) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
for (deque<T>::const_iterator it = deq.begin(); it != deq.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
deque<int> deq;
//尾插法插入元素
for (int i = 0; i < 5; i++) {
deq.push_back(i);
}
//遍历方式1:重载运算符
for (int i = 0; i < deq.size(); i++) {
//重载运算符[]:读写指定索引位置index的元素。
cout << deq[i] << " "; //0 1 2 3 4
}
cout << endl;
//遍历方式2:成员函数at()
for (int i = 0; i < deq.size(); i++) {
//重载运算符[]:读写指定索引位置index的元素。
cout << deq.at(i) << " "; //0 1 2 3 4
}
cout << endl;
//修改元素1:重载运算符
deq[4] *= 10;
printDeque<int>(deq); //0 1 2 3 40
//修改元素2:成员函数at()
deq.at(0) = -1;
printDeque<int>(deq); //-1 1 2 3 40
//获取第1个元素
cout << "第1个元素:" << deq.front() << endl; //-1
//获取最后1个元素
cout << "最后1个元素:" << deq.back() << endl; //40
return 0;
}
7 deque排序【sort()】
作用:利用STL中的排序算法的全局函数sort()
,实现对deque容器的元素排序。
算法:sort(iterator begin, iterator end)
对迭代器指向位置区间[start, end)
的所有元素进行排序,默认升序排序。
例:sort(deq.begin(), deq.end());
注1:使用
sort()
函数实现排序时,需包含标准算法头文件#include <algorithm>
。
注2:支持随机访问迭代器的容器(vector
、deque
),均可直接使用sort()
全局函数实现排序。
STL不同容器的迭代器类型:
容器种类 | 迭代器类型 |
---|---|
vector | 随机访问迭代器 |
deque | 随机访问迭代器 |
list | 双向迭代器 |
set / multiset | 双向迭代器 |
map / multimap | 双向迭代器 |
stack | 不支持迭代器 |
queue | 不支持迭代器 |
priority_queue | 不支持迭代器 |
示例:deque元素排序
#include <iostream>
using namespace std;
#include <deque> //包含头文件
#include <algorithm> //标准算法头文件
//函数模板:遍历deque容器的通用函数
template<typename T>
void printDeque(const deque<T>& deq) { //形参使用const,避免被修改
//形参使用const后,遍历时需使用只读迭代器const_iterator
for (deque<T>::const_iterator it = deq.begin(); it != deq.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
deque<int> deq;
deq.push_back(17);
deq.push_back(9);
deq.push_back(20);
deq.push_front(8);
deq.push_front(0);
deq.push_front(2);
cout << "排序前:" << endl;
printDeque<int>(deq); //2 0 8 17 9 20
//排序
sort(deq.begin(), deq.end());
cout << "排序后:" << endl;
printDeque<int>(deq); //0 2 8 9 17 20
return 0;
}
8 案例练习:评委打分
案例描述:
10位评委分别对5位选手打分,去除最高分与最低分,剩余评分取平均值作为选手得分。
思路:vector容器存储选手对象,deque容器存储评分值。
①使用vector容器存储5名选手的对象;
②遍历vector容器,对每个选手对象,通过for循环将10位评委的得分,存储至deque容器;
③sort算法对deque容器排序,并删除最低分和最高分;
④遍历deque容器,计算平均分。
注:针对不同需求使用合适的容器操作数据,可提升代码效率。
#include <iostream>
using namespace std;
#include <vector>
#include <deque>
#include <algorithm> //sort()排序
#include <string>
#include <ctime> //随机数种子
class Player {
public:
string name;
int avg;
Player(string name, int avg) {
this->name = name;
this->avg = avg;
}
};
//1.添加选手信息
void addPlayers(vector<Player> &v) {
string nameSeed = "ABCDE";
for (int i = 0; i < 5; i++) {
string name = "选手";
name += nameSeed[i]; //拼接
int avg = 0;
//创建Player对象
Player p(name, avg);
//向vector添加Player对象
v.push_back(p);
}
}
//2.为选手打分
void setScore(vector<Player> &v) {
//遍历vector容器
for (vector<Player>::iterator it = v.begin(); it != v.end(); it++) {
//创建deque容器,保存分数
deque<int> deq;
for (int i = 0; i < 10; i++) {
//创建随机数(60~100)
int score = rand() % 41 + 60;
deq.push_back(score);
}
//查看得分信息
cout << "姓名:" << it->name << ",分数:" << endl;
for (deque<int>::iterator dit = deq.begin(); dit != deq.end(); dit++) {
cout << *dit << " ";
}
cout << endl;
//排序deque容器
sort(deq.begin(), deq.end());
//去掉最高分
deq.pop_back();
//去掉最低分
deq.pop_front();
/* 求平均分 */
int sum = 0;
for (deque<int>::iterator dit = deq.begin(); dit != deq.end(); dit++) {
sum += *dit;
}
int avg = sum / deq.size();
//成员属性赋值
it->avg = avg;
}
}
//3.打印得分信息
void showInfo(vector<Player> &v) {
for (vector<Player>::iterator it = v.begin(); it != v.end(); it++) {
cout << "姓名:" << it->name << ",得分:" << it->avg << endl;
}
}
int main() {
//创建随机数种子
srand((unsigned int)time(NULL));
//创建存储选手对象的vector容器
vector<Player> v;
//1.添加选手信息
addPlayers(v);
//2.为选手打分
setScore(v);
//3.打印得分信息
showInfo(v);
return 0;
}