deque与vector非常相似,不仅可在尾部插入和删除,还可在头部插入和删除,但是内部的数据机制和执行性能与vector不同,一般来说,当考虑到容器元素的内存分配策略和操作的性能时,deque比vector有优势。
-
技术原理
deque的元素数据采用分块的线性结构进行存储,如下图所示。deque分成若干线性存储块,称为deque块,所以的deque块使用一个Map块进行管理,每个Map数据项记录各个deque块的首地址。Map是deque的中心部件,将先于deque块,依照deque的个数计算deque的块数,作为Map块的数据项数,创建出Map块。
在Map块和deque块的结构下,deque使用了两个迭代器M_start和M_finish,对首个deque块和末个deque进行访问。
M_start用于push_front函数,M_finish用于push_back函数,所以能在队首和队尾高效的添加元素。 -
deque应用基础
deque对象的创建、初始化赋值、元素的遍历访问、反向遍历与vector相同,只是把vector换成deque,这里就不多加赘述了。
2.1元素的插入
由于deque使用了两个迭代器分别指向双端队列的首尾,因此,deque具有高效的头部插入元素的函数push_back()。其他位置的插入,将涉及相关元素的移位拷贝,例如insert函数。直接上简单明了的代码:
#include <QCoreApplication>
#include <iostream>
#include <deque>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
deque<int> d;
d.push_back(6);
d.push_back(7);
d.push_front(5);//头部插入5
for(int i=0;i<d.size();i++)
{
cout << d[i] << ' ';
}
cout << endl;
d.insert(d.begin() +1,9);//在第二个元素前插入9
for(int j=0;j<d.size();j++)
{
cout << d[j] << ' ';
}
cout << endl;
return a.exec();
}
运行结果:
2.2元素的删除
直接上一看就懂的代码
#include <QCoreApplication>
#include <iostream>
#include <deque>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
deque<int> d;
d.push_back(4);
d.push_back(5);
d.push_back(3);
d.push_back(3);
d.push_back(3);
d.push_back(6);
for(int i=0;i<d.size();i++)
{
cout << d[i] << ' ';
}
cout << endl;
d.erase(d.begin()+1); //删除第二个元素d[1]
d.pop_front(); //删除第一个元素
d.pop_back(); //删除末尾元素
for(int j=0;j<d.size();j++)
{
cout << d[j] << ' ';
}
cout << endl;
d.clear();
cout << "执行clear()" << endl << "全部清除deque元素" <<endl;
return a.exec();
}
运行结果:
2.3deque的交换
废话不多说,看代码就能懂
#include <QCoreApplication>
#include <iostream>
#include <deque>
using namespace std;
void print(deque<int>& d) //元素打印
{
for(int j=0;j<d.size();j++)
{
cout << d[j] << ' ';
}
cout << endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
deque<int> d1;
d1.push_back(3);
d1.push_back(4);
d1.push_back(5);
cout << "d1=";
print(d1);
deque<int> d2;
d2.push_back(7);
d2.push_back(8);
d2.push_back(9);
cout << "d2=";
print(d2);
d1.swap(d2); //d1与d2交换
cout << "d1与d2交换后" << endl;
cout << "d1=";
print(d1);
cout << "d2=";
print(d2);
return a.exec();
}
运行结果:
2.4deque其他常用函数
简单粗暴的上代码:
#include <QCoreApplication>
#include <iostream>
#include <deque>
#include<string>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
deque<string> d1;
cout << "d1是否为空:" << d1.empty() << endl; //判断容器是否为空,是返回true,否则false
d1.push_back("红楼梦");
d1.push_back("源氏物语");
d1.push_back("教父");
d1.push_back("水浒传");
d1.push_back("24史");
deque<string>::iterator i,iend;
iend=d1.end();
for(i=d1.begin();i!=iend;i++)
{
cout << *i << " ";
}
cout << endl;
cout << "deque首元素为:" << d1.front() << endl;
cout << "deque末元素为:" << d1.back() << endl;
cout << "deque元素个数为:"<< d1.size() << endl;
cout << "deque最大元素个数为:"<< d1.max_size() << endl;
return a.exec();
}
运行结果:
3. 小结
deque双端队列容器采用分块的线性结构来存储数据,两个迭代器分别指向容器的首尾元素,具有高效的删除首尾元素的push_front和pop_front函数。由于deque容器是以deque块为单位进行内存分配,并使用了二级的Map进行管理,因此不易于实现类似于vector的capacity和reverse函数,而且deque容器也不需要这样的获取和调整容器大小的函数。