C++ STL(四):deque容器

本文详细介绍了C++ deque容器的基本概念,包括构造函数、赋值操作、大小调整、插入与删除、数据存取、排序以及一个评委打分的实际案例。deque的特点在于高效头部和尾部操作,对比vector的查询性能。
摘要由CSDN通过智能技术生成


1 deque容器基本概念

作用双端数组,可在容器的头部尾部插入或删除元素。

deque容器的迭代器:支持随机访问的迭代器,可跳跃式访问容器元素。

deque与vector区别
总结:deque头插、头删,查询/访问;vector头插、头删慢,查询/访问快。
(1)vector容器属于单端数组头部插入或删除元素的效率低,需要移动所有元素,且数据量越大,效率越低。
deque容器属于双端数组,支持头部插入或删除元素,效率高于vector容器。

(2)vector访问元素的速度快于deque
vector内部采用连续的线性空间
deque内部采用中央控制器数据缓冲区。当访问至当前缓冲区的末尾时,需通过中央控制器查找下一缓冲区的地址,再访问下一缓冲区的数据。


deque的内部工作原理(内部结构)
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);:有参构造函数,使用nelem元素进行初始化。
(4)deque(const deque &deq);:拷贝构造函数,使用已有deque对象初始化新的对象。

注:当遍历vectordeque容器的元素时:
若希望遍历过程中元素不被修改,可使用只读迭代器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);:使用nelem元素,对当前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:支持随机访问迭代器的容器(vectordeque),均可直接使用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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值