c++编程(16)——STL(4)deque

欢迎来到博主的专栏:c++编程
博主ID:代码小豪


deque

deque的全称是double ended queue,译为双端队列,如何理解这个双端呢?我们以vector为例,vector插入元素和删除元素都是只改变后端的数据结构。
在这里插入图片描述
而deque可以在前端和后端进行数据的插入与删除(虽然vector也可以头删头插,但是前端是不会改变的,只有后端改变)。
在这里插入图片描述
其实这种数据结构在逻辑上和单链表非常类似,但是不同的是deque保存数据的并不是节点,而是像vector那样的顺序储存。总而言之,deque的底层的复杂程度高于vector和list,博主打算将deque的底层放在模拟实现上讲解。

deque的优劣势

如果我们想要一个线性表来管理数据,那么大多数人都会选择使用顺序表或者链表,如果想要数据的删除和插入效率高,就选择链表,如果想要随机访问数据,那么就选择顺序表,而deque做到了两个条件都具备,其数据的插入和删除效率高于vector,又可以随机访问数据。

那么deque这么强势,那么以后如果要创建一个线性表,是不是直接用deque就行了?当然不是,虽然deque集百家之长,但是并非全面优秀,其功能虽然多,但是效率未必最佳,我们来对比一下deque、list、vector在执行不同操作时的效率。

操作dequevectorlist
头插、尾插O(1)O(N)O(1)
插入和删除略高于vectorO(N)O(1)效率最好
随机访问效率低于vectorO(1)无法随机访问

可以发现、在deque的头部插入和删除的效率与list持平,因此deque也经常用于频繁进行头尾插入的场景当中,比如栈和队列就非常喜欢用deque作为容器。但是除此之外更多的选择则是list和vector。

deque的操作

vector、list、string、deque都属于线性表的数据结构,而线性表的数据的插入、删除操作的效果都是类似的,区别是在于底层的实现不同,但是博主在这里并不打算讲解deque的底层,因此跳过deque的数据修改操作。

constructor

default (1)	
explicit deque (const allocator_type& alloc = allocator_type());
fill (2)	
explicit deque (size_type n, const value_type& val = value_type(),
                const allocator_type& alloc = allocator_type());
range (3)	
template <class InputIterator>
  deque (InputIterator first, InputIterator last,
         const allocator_type& alloc = allocator_type());
copy (4)	
deque (const deque& x);

defalut构造
构造一个空的deque容器,没有任何元素。

deque<int> dq1;//空的deque容器
dq1.push_back(1);
dq1.push_back(2);
dq1.push_back(3);
dq1.push_back(4);

for (auto& e : dq1)
{
	cout << e << ' ';//1 2 3 4
}

填充(fill)构造
向deque容器填充n个值为val的元素

deque<int> dq2(5, 10);
for (auto& e : dq2)
{
	cout << e << ' ';//10 10 10 10 10
}
cout << endl;

范围(range)构造
向deque传入迭代器区间,将迭代器区间的元素按照顺序拷贝到deque当中

string str1("hello world");
deque<char> dq3(str1.begin(), str1.end());
for (auto& e : dq3)
{
	cout << e ;//hello world
}

将str1中的开头和结尾的迭代器传入deque容器当中,容器会根据传入的迭代器[begin(),end())区间内的所有元素拷贝到容器当中,反向迭代区间也是同理。

拷贝(copy)构造
将相同类型的deque容器拷贝到一个新容器当中,元素的顺序保持一致。

deque<char>dq4(dq3);//拷贝容器dq3
for (auto& e : dq4)
{
	cout << e;//hello world
}

c++11标准还引入了初始化列表构造。deque容器会按照顺序拷贝初始化列表({})中的元素。

deque<int> dq5{1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto& e : dq5)
{
	cout << e << ' ';//1,2,3,4,5,6,7,8,9
}

元素访问

deque支持随机访问,因此可以向vector一样使用下标访问deque元素。

deque<int> dq5{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < dq5.size(); i++)
{
	cout << dq5[i];//1,2,3,4,5,6,7,8,9
}

虽然deque和vector都支持随机访问容器元素,但是这并不意味着这两个容器的效率相同。我们可以用sort()算法来检验。

sort()算法是定义在<algorith>库中的函数,这个库是STL的算法库,支持对STL容器进行一些操作。sort()函数是将vector和deque进行排序操作,这就意味着会进行大量的下标访问操作(排序算法大多都会有下标访问操作)。

void TestAccessSpeed()
{
	srand((unsigned int)time(nullptr));//定义在stdlib.h的文件

	vector<int> v1;
	deque<int> d1;
	int i = 0;
	int num = 0;

	while (i < 100000)//向vector和deque当中插入100000个相同的数据
	{
		num = rand();//定义在stdlib.h的文件
		v1.push_back(num);
		d1.push_back(num);
		i++;
	}

	int begin1 = clock();//begin1是开始排序的时间
	sort(v1.begin(), v1.end());//vector开始排序
	int end1 = clock();//end1是结束排序的时间

	int begin2 = clock();
	sort(d1.begin(), d1.end());
	int end2 = clock();

	cout << "vector排序的时间:" << end1 - begin1 << endl;
	cout << "deque排序的时间:" << end2 - begin2 << endl;
}

经过测试,vector的排序时间比deque快上几倍。这说明了deque下标访问的效率其实是低于vector的。

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码小豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值