前面学习了vector单端数组容器,既然有单端也就有双端。vector是限制在尾部新增和删除元素,实际上还有一种数据结构是两头都可以添加和删除元素,这里开始学习deque双端数组容器。
1.deque和vector区别
vector对于头部的插入删除效率低,数据量越大,效率越低。
deque相对而言,对头部的插入删除速度会比vector快
vector访问元素时的速度会比deque快,这和两者内部实现有关。
上图中,中间这个多个方格就是双端数组,两头都有插入和删除方法,中间还有insert()方法。有两个迭代器begin()和end()。
2.deque的工作原理
内部有一个重要的中控器的概念
1)每一行都是一个连续的内存地址,叫缓冲器,缓冲器首位都有余量提供插入新元素
2)例如0x03这个节点对应得缓冲区域,最后元素插入满,会新建一个类似0x04的节点, 找一个连续内存空间,用0x04记录这个连续内存空间,开始用来尾部插入数据元素
3)同理,头部0x01之上可以继续添加节点,节点指向不同缓冲区
4)这种原理,导致双端数据查找元素会比vector慢,因为不是所有元素都是在连续的内存空间,如果不连续,需要通过节点去查找元素。但是这种头尾插入元素效率高。
3.deque的构造函数
先来看看deque的构造函数
deque<T> deq; // 默认构造函数
deque(begin, end); //构造函数将[begin, end]区间中的元素拷贝给本身
deque(n, ele) // 构造函数将n个ele拷贝给本身
deque(const deque &deq); //拷贝构造函数
先来一个简单的默认构造,我们这里也是提前结束插入元素和遍历方法
#include <iostream>
#include <string>
#include <deque>
using namespace std;
void printDeque(const deque<int> &d)
{
// for循环迭代器遍历容器内元素
for(deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int> d;
for(int i=0; i<10; i++)
{
d.push_back(i);
}
printDeque(d);
}
int main()
{
test01();
system("pause");
return 0;
}
上面在遍历方法中参数 添加了const修饰,注意迭代器也需要使用const的迭代器,这样保证在迭代过程中不会修改容器中的元素。
接着试试其他的构造函数
#include <iostream>
#include <string>
#include <deque>
using namespace std;
void printDeque(const deque<int> &d)
{
// for循环迭代器遍历容器内元素
for(deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int> d;
for(int i=0; i<10; i++)
{
d.push_back(i);
}
printDeque(d);
// 2构造使用迭代器
deque<int> d1(d.begin()+1, d.end()-3);
printDeque(d1);
// 3 拷贝构造
deque<int> d2(d1);
printDeque(d2);
}
int main()
{
test01();
system("pause");
return 0;
}
运行效果
4.deque的赋值操作
其实这个赋值操作和vector基本一样。
下面代码来练习一下 第一个和第二个函数
#include <iostream>
#include <string>
#include <deque>
using namespace std;
void printDeque(const deque<int> &d)
{
// for循环迭代器遍历容器内元素
for(deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int> d;
for(int i=0; i<10; i++)
{
d.push_back(i);
}
printDeque(d);
// 赋值操作1 通过=号
deque<int> d1 = d;
printDeque(d1);
// 赋值操作2 通过assign函数
deque<int> d2;
d2.assign(d1.begin() + 2, d1.end() -3);
printDeque(d2);
}
int main()
{
test01();
system("pause");
return 0;
}
基本上是以重载=符号比较常用。