c++ 双端队列 deque用法解析

1、deque的作用

deque即双端队列,它的用法非常强大,可以代替栈stack、队列queue、向量容器vector等等。

因为它能像栈一样后进先出、也能像queue一样先进先出,还能像vector一样随机访问,同时支持sort、lower_bound、reverse等内置函数

但是顾名思义,它的主要功能还是双端队列,可以随时从头添加或删除元素,也可以随时从末尾添加或者删除元素

2、deque的定义

deque的头文件就是deque使用时添加头文件即可

#include<deque>

定义的方式:
deque<储存的类型> 容器名

例如:

deque<int> q;//定义一个储存int类型的双端队列
deque<double> q;//定义一个储存double类型的双端队列
deque<string> q;//定义一个储存string类型的双端队列
deque<自定义结构体> q;//还可以定义一个储存结构体或类的双端队列

当然也可以定义队列数组:

deque<int> q[n];//定义一个储存int类型的双端队列数组
deque<double> q[n];//定义一个储存double类型的双端队列数组
deque<string> q[n];//定义一个储存string类型的双端队列数组
deque<自定义结构体> q[n];//还可以定义一个储存结构体或类的双端队列数组
//n为队列的大小

3、deque的成员函数

//这些都是必会的成员函数
size()//返回返回容器中元素个数
begin()//返回头部迭代器
end()//返回尾部+1迭代器
rbegin()//返回逆首部迭代器
rend()//返回逆尾部-1迭代器
front()//返回首个元素
back()//返回尾部元素
push_front()//在前面添加一个函数
emplace_frontback()//和push_front()是一样的作用
push_back()//在末尾添加一个函数
emplace_back()//和push_back()是一样的作用
pop_front()//弹出第一个个元素
pop_back()//弹出最后一个元素
empty()//判断是否为空
insert()//在指定位置插入元素
erase()//在指定位置删除元素
clear()//清空容器

详细解析:
(1)size()
size()是最常用的成员函数了,常用于deque的遍历和元素个数的查询

(2)push_back()
除了初始化以外,push_front()和push_back()是deque最重要的修改函数了,复杂度为O(1),而insert()的复杂度为O(n),差距明显

(3)front()、back()
查询首元素和未元素,其实通过随机访问,q[0]、q[q.size()-1]是可以达到相同效果的,用front()和back()显得专业点

(4)begin()、end()
通常用来方便排序的,也可以用来遍历,但没必要,通过下标遍历更简单快捷,rbegin()、rend()则可以用来逆序排序

(5)insert()
insert (position, x );
insert (position, n, x );
insert (position, first, last );
插入新的元素,
第一个函数,在迭代器指定的位置前插入值为x的元素
第二个函数,在迭代器指定的位置前插入n个值为x的元素
第三个函数,在迭代器指定的位置前插入另外一个容器的一段序列迭代器first到last
复杂度很高,迫不得已不使用

(6)erase()
erase ( position );
erase (first, last );
删除元素或一段序列
同样地,复杂度很高,迫不得已不使用

示例代码:

#include<iostream>//c++标准输入输出流 
#include<deque>//deque的头文件 
#include<algorithm>//算法头文件,包含大量内置算法 
using namespace std;//std即standard的缩写,使用标准命名空间
void print(auto q){
    
    //遍历函数 
	for(auto c:q){
    
    
		cout<<c<<' ';
	}
	cout<<endl;
} 
int main(){
    
    
	deque<int> q;//定义一个储存int类型的双端队列 
	q.emplace_back(2);
	q.emplace_back(1);//在双端队列末尾添加元素1
	q.emplace_back(2);
	q.emplace_back(3);
	q.emplace_back(6);
	q.emplace_back(7);
	q.emplace_back(8);
	cout<<"现在有的元素:";
	print(q); 
	cout<<endl; 
	
	
	q.pop_front();//弹出首元素 
	cout<<"q.pop_front()弹出第一个元素后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	q.pop_back();//弹出末尾元素 
	cout<<"q.pop_back()弹出末尾元素后,现在有的元素:"; 
	print(q); 
	cout<<endl;
	
	q.emplace_front(4);//在双端队列前添加元素4
	cout<<"q.emplace_front(4)添加元素4后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	q.emplace_back(5);//在双端队列末尾添加元素5
	cout<<"q.emplace_back(5)添加元素5后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	reverse(q.begin(),q.end());//翻转函数 
	cout<<"reverse(q.begin(),q.end())翻转元素后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	sort(q.begin(),q.end());//排序函数 
	cout<<"sort(q.begin(),q.end())排序元素后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	sort(q.rbegin(),q.rend());//排序函数 
	cout<<"sort(q.rbegin(),q.rend())逆序元素后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	q[0]=10;//通过下标更改值
	cout<<"q[0]=10更改q[0]的值后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	q.insert(q.begin()+1,5);//第二个位置插入5 
	cout<<"q.insert(q.begin()+1,5)第二个位置插入5后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	q.insert(q.begin()+1,2,6);//第二个位置插入2个6 
	cout<<"q.insert(q.begin()+1,2,6)第二个位置插入2个6后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	q.erase(q.begin()+1);//删除第2个元素 
	cout<<"q.erase(q.begin()+1)删除第2个元素后,现在有的元素:"; 
	print(q); 
	cout<<endl; 
	
	q.erase(q.begin()+1,q.begin()+2);//删除第2至第3个位置的元素 
	cout<<"q.erase(q.begin()+1,q.begin()+2)删除第2至第3个位置的元素 ,现在有的元素:"; 
	print(q); 
	cout<<endl;
	
	cout<<"目前的q.size()="<<q.size()<<endl<<endl; 
	
	//判断是否非空
	cout<<"q.empty()="<<q.empty()<<",0代表非空,1代表空的"<<endl<<endl; 
	
	q.clear();//清空容器 
	cout<<"q.clear()清空容器后 ,现在有的元素:"; 
	print(q); 
	cout<<endl;
	
	
	cout<<"目前的q.size()="<<q.size()<<endl<<endl; 
	
	//判断是否非空
	cout<<"q.empty()="<<q.empty()<<",0代表非空,1代表空的"<<endl<<endl; 
}

运行结果:

现在有的元素:2 1 2 3 6 7 8

q.pop_front()弹出第一个元素后,现在有的元素:1 2 3 6 7 8

q.pop_back()弹出末尾元素后,现在有的元素:1 2 3 6 7

q.emplace_front(4)添加元素4后,现在有的元素:4 1 2 3 6 7

q.emplace_back(5)添加元素5后,现在有的元素:4 1 2 3 6 7 5

reverse(q.begin(),q.end())翻转元素后,现在有的元素:5 7 6 3 2 1 4

sort(q.begin(),q.end())排序元素后,现在有的元素:1 2 3 4 5 6 7

sort(q.rbegin(),q.rend())逆序元素后,现在有的元素:7 6 5 4 3 2 1

q[0]=10更改q[0]的值后,现在有的元素:10 6 5 4 3 2 1

q.insert(q.begin()+1,5)第二个位置插入5后,现在有的元素:10 5 6 5 4 3 2 1

q.insert(q.begin()+1,2,6)第二个位置插入26后,现在有的元素:10 6 6 5 6 5 4 3 2 1

q.erase(q.begin()+1)删除第2个元素后,现在有的元素:10 6 5 6 5 4 3 2 1

q.erase(q.begin()+1,q.begin()+2)删除第2至第3个位置的元素 ,现在有的元素:10 5 6 5 4 3 2 1

目前的q.size()=8

q.empty()=0,0代表非空,1代表空的

q.clear()清空容器后 ,现在有的元素:

目前的q.size()=0

q.empty()=1,0代表非空,1代表空的

四、deque的遍历

(1)迭代器iterator

代码:

#include<iostream>
#include<deque>
using namespace std;
int main(){
    
    
	deque<int> q;//定义 
	q.emplace_back(1);//插入元素1 
	q.emplace_back(3);//插入元素3
	q.emplace_back(2);//插入元素2
	deque<int>::iterator it;//使用迭代器
	for(it=q.begin();it!=q.end();it++){
    
    
		cout<<*it<<' ';
	} 
} 

运行结果:

1 3 2

(2)下标遍历

代码:

#include<iostream>
#include<deque>
using namespace std;
int main(){
    
    
	deque<int> q;//定义 
	q.emplace_back(1);//插入元素1 
	q.emplace_back(3);//插入元素3
	q.emplace_back(2);//插入元素2
	for(int i=0;i<q.size();i++){
    
    
		cout<<q[i]<<' ';
	} 
} 

运行结果:

1 3 2

(3)foreach遍历

代码:

#include<iostream>
#include<deque>
using namespace std;
int main(){
    
    
	deque<int> q;//定义 
	q.emplace_back(1);//插入元素1 
	q.emplace_back(3);//插入元素3
	q.emplace_back(2);//插入元素2
	for(int c:q){
    
    
		cout<<c<<' ';
	} 
} 

运行结果:

1 3 2

两种逆序遍历:

代码:

#include<iostream>
#include<vector>
using namespace std;
int main(){
    
    
	vector<int> q;//定义 
	q.emplace_back(1);//插入元素1 
	q.emplace_back(3);//插入元素3
	q.emplace_back(2);//插入元素2
	
//	迭代器法 
	vector<int>::reverse_iterator it;//使用迭代器
	for(it=q.rbegin();it!=q.rend();it++){
    
    
		cout<<*it<<' ';
	} 
	cout<<endl;
	
//	下标遍历法
	for(int i=q.size()-1;i>=0;i--){
    
    
		cout<<q[i]<<' ';
	} 
} 

运行结果:

2 3 1
2 3 1

foreach虽然简单易用,但是不支持逆序遍历

有小伙伴发现dev不能编译部分代码,那是因为dev还未支持c++11,可以看这篇文章解决
dev使用c++11教程

是不是很简单呢?

刚接触肯定会觉得难,多些做题多些用,熟悉了就容易了,兄弟萌,加油!!!

文章尚有不足,欢迎大牛们指正

感谢观看,点个赞吧

猜你喜欢

转载自blog.csdn.net/weixin_52115456/article/details/128940298