『C++』deque容器的简单介绍

deque简单介绍

在这里插入图片描述
看到英文不要慌,翻译在下面O(∩_∩)O哈哈~:

  1. deque(发音类似"deck"),是双端队列不规则的首字母缩写,双端队列是动态大小的序列式容器,其可以向两端进行伸缩
  2. 特定的库可以以不同的方式实现deque,但通常都是一种动态数组。不论在何种情况下,它都允许通过随机访问迭代器直接访问单个元素,可以根据需要动态的伸缩。
  3. 因此,deque提供了一些与vector相似的功能,但deque在头部和尾部进行数据插入和删除操作更加高效。与vector不同的是,deque不能保证所有的元素存储在连续的空间内,在deque中通过指针加偏移量方式访问元素可能会导致非法的操作
  4. vector与deque提供了相似的接口,因此其具有类似的用途,但是内部的实现原理不同vector使用了动态数组,该数组通常需要动态增长deque中的元素可能分散在不同的存储块中,在deque中保存了一些必要的信息,通常用来在常数范围内直接访问deque中的任何一个元素,所以deque的内部实现比vector更复杂,但是这些额外信息使得deque在某些情况下更加的高效,特别是在序列比较大,重新分配成本比较高的情况下
  5. 除了频繁在头部或尾部进行插入和删除的操作外,deque比list和forward_list的性能更差

在这里插入图片描述

deque的使用

构造函数

函数声明接口说明
deque();构造空的双端队列
deque(n, val = val_type());用n个值为val的元素构造双端队列
deque(InputIterator first, InputIterator last);用[first, last)的区间构造双端队列
deque(const deque& x);双端队列的拷贝构造函数
#include <iostream>
#include <deque>

void Display(const std::deque<int>& d){
	for(const auto& e : d){
		std::cout << e << " ";
	}
	std::cout << std::endl;
}

int main(){
	// 空的双端队列
	std::deque<int> d1;
	Display(d1);

	// 用10个3来初始化双端队列
	std::deque<int> d2(10, 3);
	Display(d2);

	int arr[] = {
		1, 2, 3, 4, 5
	};

	// 用数组的区间构造双端队列
	std::deque<int> d3(arr, arr + sizeof(arr) / sizeof(arr[0]));
	Display(d3);

	// 拷贝构造
	std::deque<int> d4(d3);
	Display(d4);

	return 0;
}
[sss@aliyun deque]$ !g++
g++ constructor.cc -o constructor -std=c++11
[sss@aliyun deque]$ ./constructor 

3 3 3 3 3 3 3 3 3 3 
1 2 3 4 5 
1 2 3 4 5 

迭代器

双端队列底层是一段假想的连续空间实际是分段连续的,为了维护其“整体连续”的假象,需要对其迭代器进行特殊处理
在这里插入图片描述
在这里插入图片描述

函数声明接口说明
[begin(),end())begin:容器起始位置;end:最后一个元素的下一个位置。
[rbegin(),rend())反向迭代器rbegin在end位置,rend在begin位置。
[cbegin(),cend())const迭代器,与begin和end位置相同,但不能修改其空间内容。
[crbegin(),crend())const反向迭代器,crbegin在cend位置,crend在cbegin位置。
#include <iostream>
#include <deque>

int main(){
	int arr[] = {
		1, 2, 3, 4, 5
	};

	std::deque<int> d(arr, arr + sizeof(arr) / sizeof(arr[0]));

	// 正向迭代器打印d中的元素
	std::deque<int>::iterator it = d.begin();
	while(it != d.end()){
		std::cout << *it << " ";
		++it;
	}
	std::cout << std::endl;

	// 反向迭代器打印d中的元素
	std::deque<int>::reverse_iterator rit = d.rbegin();
	while(rit != d.rend()){
		std::cout << *rit << " ";
		++rit;
	}
	std::cout << std::endl;

	return 0;
}
[sss@aliyun deque]$ !g++
g++ iterator.cc -o iterator
[sss@aliyun deque]$ ./iterator 
1 2 3 4 5 
5 4 3 2 1 

容量相关操作

函数声明接口说明
size();返回deque中有效元素的个数。
empty();检测deque是否为空,为空返回true,否则返回false。
resize(sz, value);将deque中的有效元素数量改变到sz,多出的空间用value填充。
#include <iostream>
#include <deque>

int main(){
	// 使用3个3来初始化双端队列
	std::deque<int> d(3, 3);

	// 正向迭代器打印d中的元素
	std::deque<int>::iterator it = d.begin();
	while(it != d.end()){
		std::cout << *it << " ";
		++it;
	}
	std::cout << std::endl;

	// 判断双端队列d是否为空
	std::cout << "empty(): " << d.empty() << std::endl;

	// 返回双端队列d中有效元素的数量
	std::cout << "size(): " << d.size() << std::endl;

	// 调整双端队列的有效元素数量为4,多出的部分用4来填充
	d.resize(4, 4);

	// 正向迭代器打印d中元素
	it = d.begin();
	while(it != d.end()){
		std::cout << *it << " ";
		++it;
	}
	std::cout << std::endl;

	return 0;
}
[sss@aliyun deque]$ !g++
g++ capacity.cc -o capacity
[sss@aliyun deque]$ ./capacity 
3 3 3 
empty(): 0
size(): 3
3 3 3 4 

元素访问操作

函数声明接口说明
operator[]返回deque中指定位置上元素的引用。
front();返回deque中首元素的引用。
back();返回deque中最后一个元素的引用。
#include <iostream>
#include <deque>

int main(){
	int arr[] = {
		1, 2, 3, 4, 5
	};

	// 使用数组arr初始化双端队列d
	std::deque<int> d(arr, arr + sizeof(arr) / sizeof(arr[0]));

	// 使用[]对d中的元素进行遍历
	for(size_t i = 0; i < d.size(); ++i){
		std::cout << d[i] << " ";
	}
	std::cout << std::endl;

	// 返回双端队列首部元素
	std::cout << "front(): " << d.front() << std::endl;

	// 返回双端队列尾部元素
	std::cout << "back(): " << d.back() << std::endl;

	return 0;
}
[sss@aliyun deque]$ !g++
g++ element_visit.cc -o element_visit
[sss@aliyun deque]$ ./element_visit 
1 2 3 4 5 
front(): 1
back(): 5

元素修改操作

函数声明接口说明
push_back()和pop_back()deque的尾插和尾删。
push_front()和pop_front()deque任意位置插入和删除。
insert(pos, value)pos位置插入value。
erase()删除pos出元素。
swap()交换两个deque中的内容。
clear()将deque中的元素清空。
#include <iostream>
#include <deque>

void Display(const std::deque<int>& d){
	for(const auto& e : d){
		std::cout << e << " ";
	}
	std::cout << std::endl;
}

int main(){
	// 空的双端队列d
	std::deque<int> d;
	Display(d);

	// 尾插0、1,头插2,0后面插入3
	d.push_back(0);
	d.push_back(1);
	d.push_front(2);
	d.insert(d.begin() + 2, 3);
	Display(d);

	// 尾删、使用erase进行头删
	d.pop_back();
	d.erase(d.begin());
	Display(d);

	std::deque<int> temp(d);
	// 清空d
	d.clear();
	std::cout << "d: ";
	Display(d);
	std::cout << "temp: ";
	Display(temp);

	// d和temp交换
	std::cout << std::endl <<  "after swap:" << std::endl;
	d.swap(temp);
	std::cout << "d: ";
	Display(d);
	std::cout << "temp: ";
	Display(temp);

	return 0;
}
[sss@aliyun deque]$ !g++
g++ modify.cc -o modify -std=c++11
[sss@aliyun deque]$ ./modify 

2 0 3 1 
0 3 
d: 
temp: 0 3 

after swap:
d: 0 3 
temp: 

注意

#include <iostream>
#include <algorithm>
#include <deque>

int main(){
	int arr[] = {
		3, 5, 0, 1, 6, 9
	};

	// 使用数组初始化双端队列d
	std::deque<int> d(arr, arr + sizeof(arr) / sizeof(arr[0]));

	// 正向迭代器遍历元素
	std::deque<int>::iterator it = d.begin();
	while(it != d.end()){
		std::cout << *it << " ";
		++it;
	}
	std::cout << std::endl;

	// 排序
	std::sort(d.begin(), d.end());

	// 正向迭代器遍历打印
	it = d.begin();
	while(it != d.end()){
		std::cout << *it << " ";
		++it;
	}
	std::cout << std::endl;

	return 0;
}
[sss@aliyun deque]$ g++ sort.cc -o sort
[sss@aliyun deque]$ ./sort 
3 5 0 1 6 9 
0 1 3 5 6 9 

deque中排序操作的效率是非常低的,因为deque中的元素在底层的实现上是不连续的。可以考虑将deque中的元素拷贝到一个vector中,然后排序之后,再将元素拷贝回来
deque在序列式容器中算是比较鸡肋的存在,虽然它的野心很大,想要替代vector和list,但是呵呵。
deque最大的用处就是作为标准库中stack和queue的底层结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值