deque

  1. deque的介绍
  2. deque的使用
  3. deque的应用

1. deque的介绍

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

2. deque的使用
2.1deque的构造
在这里插入图片描述
2.2 deque的迭代器
双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”的假象,落在了deque的迭代器身上。下图为deque的原理图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//双端队列迭代器的设计
#include <iostream>
using namespace std;
template<class T,class Ref, class Ptr>
class DequeIterator
{
public:
    typedef DequeIterator<T, Ref, Ptr>self;
    ref operator*()
    {
         return *cur;
    }
    DequeIterator<T, Ref, Ptr>& operator++()
    {
         cur++;
         if (cur == last)
         {
             node++;
             first = *node;//第一次解引用后就是下一段缓冲区第一个元素的地址,第二次解引用后就是下一段缓冲区第一个元素的值
             last = first + bufferLen;
             cur = first;
         }
         return *this;
    }
private:
    T* first;
    T* last;
    T* cur;
    T** node;//指向中控的二级指针
};
template <class>
class Deque
{
public:
    iterator begin()
    {
         return _start;
    }
    iterator end()
    {
         return _finish;
    }
private:
    iterator _start;//(通过封装的迭代器)
    iterator _finish;//(通过封装的迭代器)
    T** map;//中控(指针数组)
};

2.3 deque的容量操作
在这里插入图片描述
2.4 deque的元素访问操作
在这里插入图片描述
2.4 deque中修改操作
在这里插入图片描述
在这里插入图片描述
2.5 deque接口应用实例

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<deque>
using namespace std;
void PrintDeque(const std::deque<int>& d)
{
	for (const auto& e : d)
		cout << e << " ";
	cout << endl;
}

	
// 测试deque的构造函数
void TestDeque1()
{
		// 构造空的双端队列
		std::deque<int> d1;

	// 用10个值为5的元素构造双端队列
	std::deque<int> d2(10, 5);
	PrintDeque(d2);
	// 用数组的区间构造双端队列
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	std::deque<int> d3(array, array + sizeof(array) / sizeof(array[0]));
	PrintDeque(d3);
	// 用d3拷贝构造d4
	std::deque<int> d4(d3);
	PrintDeque(d4);
}

// 测试deque中的迭代器
void TestDeque2()
{
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	std::deque<int> d(array, array + sizeof(array) / sizeof(array[0]));

	// 利用正向迭代器打印deque中的元素
	for (auto it = d.cbegin(); it != d.cend(); ++it)
		cout << *it << " ";
	cout << endl;
	auto cit = d.cbegin();
	//*it = 100; 该条语句编译失败,it为const迭代器,其指向空间元素值不能修改

	// 利用反向迭代器逆向打印deque中的元素
	for (auto it = d.crbegin(); it != d.crend(); ++it)
		cout << *it << " ";
	cout << endl;
}
void TestDeque3()
{
	// 列表方式初始化,C++11语法
	deque<int> d1{ 3, 4, 5 };
	// 在deque的尾部插入5,头部插入1,并打印
	d1.push_back(6);
	d1.push_front(2);
	PrintDeque(d1);
	cout << d1.size() << endl;
	cout << d1.front() << endl;
	cout << d1.back() << endl;
	// 在deque的尾部构造6,头部构造0
	// 注意:如果是内置类型元素,
	// emplace_back与push_back emplace_front与push_front的效率形同
	// 如果是自定义类型元素
	// emplace_back/emplace_front的效率更高,这两个操作直接在尾部或者头部构造元素
	// push_back/push_front的效率低,该操作时先将元素构造好,然后拷贝到尾部或头部
		d1.emplace_back(7);
	d1.emplace_front(1);
	PrintDeque(d1);
	// 在deque的begin位置插入元素0
	d1.insert(d1.begin(), 0);
	PrintDeque(d1);
	// 删除deque首部与尾部元素
	d1.pop_front();
	d1.pop_back();
	d1.erase(d1.begin());
	PrintDeque(d1);
	// 将deque中的元素清空
	d1.clear();
	cout << d1.size() << endl;
}

3. deque的应用场景
deque在序列式容器中比较鸡肋,因为如果只是简单的存储元素,使用vector即可,如果对元素任意位置进行插入或者删除操作比较多,使用list即可,所以一般很少去使用deque。deque最大的应用,就是用其作为标准库中stack,queue的底层结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值