我是靠谱客的博主 斯文摩托,最近开发中收集的这篇文章主要介绍STL序列容器详解之deque,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

参考链接

双端队列容器

deque 是 double-ended queue 的缩写,又称双端队列容器。
deque 容器也擅长在序列尾部添加或删除元素(时间复杂度为O(1)),而不擅长在序列中间添加或删除元素。
deque 容器也可以根据需要修改自身的容量和大小。
deque 还擅长在序列头部添加或删除元素,所耗费的时间复杂度也为常数阶O(1)。
deque 容器中存储元素并不能保证所有元素都存储到连续的内存空间中。
deque 容器以模板类 deque<T>(T 为存储元素的类型)的形式在 <deque>头文件中,并位于 std 命名空间中。

#include <deque>
using namespace std;

创建deque容器的几种方式

  • 创建一个没有任何元素的空 deque 容器:

    std::deque<int> d;
    
  • 创建一个具有 n 个元素的 deque 容器,其中每个元素都采用对应类型的默认值:

    std::deque<int> d(10);
    

    创建一个具有 10 个元素(默认都为 0)的 deque 容器。

  • 创建一个具有 n 个元素的 deque 容器,并为每个元素都指定初始值:

    std::deque<int> d(10, 5)
    
  • 在已有 deque 容器的情况下,可以通过拷贝该容器创建一个新的 deque 容器:

    std::deque<int> d1(5);
    std::deque<int> d2(d1);
    
  • 通过拷贝其他类型容器中指定区域内的元素(也可以是普通数组),可以创建一个新容器:

    //拷贝普通数组,创建deque容器
    int a[] = { 1,2,3,4,5 };
    std::deque<int>d(a, a + 5);
    //适用于所有类型的容器
    std::array<int, 5>arr{ 11,12,13,14,15 };
    std::deque<int>d(arr.begin()+2, arr.end());//拷贝arr容器中的{13,14,15}
    

deque容器的成员函数

函数成员函数功能
begin()返回指向容器中第一个元素的迭代器。
end()返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。
rbegin()返回指向最后一个元素的迭代器。
rend()返回指向第一个元素所在位置前一个位置的迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
size()返回实际元素个数。
max_size()返回容器所能容纳元素个数的最大值。这通常是一个很大的值,一般是 232-1,我们很少会用到这个函数。
resize()改变实际元素的个数。
empty()判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
shrink _to_fit()将内存减少到等于当前元素实际所使用的大小。
at()使用经过边界检查的索引访问元素。
front()返回第一个元素的引用。
back()返回最后一个元素的引用。
assign()用新元素替换原有内容。
push_back()在序列的尾部添加一个元素。
push_front()在序列的头部添加一个元素。
pop_back()移除容器尾部的元素。
pop_front()移除容器头部的元素。
insert()在指定的位置插入一个或多个元素。
erase()移除一个元素或一段元素。
clear()移出所有的元素,容器大小变为 0。
swap()交换两个容器的所有元素。
emplace()在指定的位置直接生成一个元素。
emplace_front()在容器头部生成一个元素。和 push_front() 的区别是,该函数直接在容器头部构造元素,省去了复制移动元素的过程。
emplace_back()在容器尾部生成一个元素。和 push_back() 的区别是,该函数直接在容器尾部构造元素,省去了复制移动元素的过程。
#include <iostream>
#include <deque>
using namespace std;
int main()
{
//初始化一个空deque容量
deque<int>d;
//向d容器中的尾部依次添加 1,2,3
d.push_back(1); //{1}
d.push_back(2); //{1,2}
d.push_back(3); //{1,2,3}
//向d容器的头部添加 0 
d.push_front(0); //{0,1,2,3}
//调用 size() 成员函数输出该容器存储的字符个数。
printf("元素个数为:%dn", d.size());
//使用迭代器遍历容器
for (auto i = d.begin(); i < d.end(); i++) {
cout << *i << " ";
}
cout << endl;
return 0;
}

deque容器迭代器

begin() 和 end()

#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<int>d{1,2,3,4,5};
//从容器首元素,遍历至最后一个元素
for (auto i = d.begin(); i < d.end(); i++) {
cout << *i << " ";
}
return 0;
}

cbegin()/cend()

#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<int>d{1,2,3,4,5};
auto first = d.cbegin();
auto end = d.cend();
//常量迭代器不能用来修改容器中的元素值
//*(first + 1) = 6;//尝试修改容器中元素 2 的值
//*(end - 1) = 10;//尝试修改容器中元素 5 的值
//常量迭代器可以用来遍历容器、访问容器中的元素
while(first<end){
cout << *first << " ";
++first;
}
return 0;
}

rbegin() 和 rend()

#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<int>d{1,2,3,4,5};
for (auto i = d.rbegin(); i < d.rend(); i++) {
cout << *i << " ";
}
return 0;
}

当向 deque 容器添加元素时,deque 容器会申请更多的内存空间,同时其包含的所有元素可能会被复制或移动到新的内存地址(原来占用的内存会释放),这会导致之前创建的迭代器失效。

#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<int>d;
d.push_back(1);
auto first = d.begin();
cout << *first << endl;
//添加元素,会导致 first 失效
d.push_back(1);
cout << *first << endl;
return 0;
}

deque容器访问元素(4种方法)

  • 采用普通数组访问存储元素的方式,访问 deque 容器中的元素:

    #include <iostream>
    #include <deque>
    using namespace std;
    int main()
    {
    deque<int>d{ 1,2,3,4 };
    cout << d[1] << endl;
    //修改指定下标位置处的元素
    d[1] = 5;
    cout << d[1] << endl;
    return 0;
    }
    
  • 使用 deque 模板类提供的 at() 成员函数:

    #include <iostream>
    #include <deque>
    using namespace std;
    int main()
    {
    deque<int>d{ 1,2,3,4 };
    cout << d.at(1) << endl;
    d.at(1) = 5;
    cout << d.at(1) << endl;
    //下面这条语句会抛出 out_of_range 异常
    //cout << d.at(10) << endl;
    return 0;
    }
    
  • front() 和 back()

    #include <iostream>
    #include <deque>
    using namespace std;
    int main()
    {
    deque<int> d{ 1,2,3,4,5 };
    cout << "deque 首元素为:" << d.front() << endl;
    cout << "deque 尾元素为:" << d.back() << endl;
    //修改首元素
    d.front() = 10;
    cout << "deque 新的首元素为:" << d.front() << endl;
    //修改尾元素
    d.back() = 20;
    cout << "deque 新的尾元素为:" << d.back() << endl;
    return 0;
    }
    

deque 容器没有提供 data() 成员函数,同时 deque 容器在存储元素时,也无法保证其会将元素存储在连续的内存空间中,因此尝试使用指针去访问 deque 容器中指定位置处的元素,是非常危险的。

#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<int> d{ 1,2,3,4,5 };
//从元素 2 开始遍历
auto first = d.begin() + 1;
//遍历至 5 结束(不包括 5)
auto end = d.end() - 1;
while (first < end) {
cout << *first << " ";
++first;
}
return 0;
}

deque容器添加和删除元素方法

除了 insert() 函数的语法格式比较多,其他函数都只有一种用法(erase() 有 2 种语法格式)

#include <deque>
#include <iostream>
using namespace std;
int main()
{
deque<int>d;
//调用push_back()向容器尾部添加数据。
d.push_back(2); //{2}
//调用pop_back()移除容器尾部的一个数据。
d.pop_back(); //{}
//调用push_front()向容器头部添加数据。
d.push_front(2);//{2}
//调用pop_front()移除容器头部的一个数据。
d.pop_front();//{}
//调用 emplace 系列函数,向容器中直接生成数据。
d.emplace_back(2); //{2}
d.emplace_front(3); //{3,2}
//emplace() 需要 2 个参数,第一个为指定插入位置的迭代器,第二个是插入的值。
d.emplace(d.begin() + 1, 4);//{3,4,2}
for (auto i : d) {
cout << i << " ";
}
//erase()可以接受一个迭代器表示要删除元素所在位置
//也可以接受 2 个迭代器,表示要删除元素所在的区域。
d.erase(d.begin());//{4,2}
d.erase(d.begin(), d.end());//{},等同于 d.clear()
return 0;
}

insert() 函数的用法
insert() 函数的功能是在 deque 容器的指定位置插入一个或多个元素。

#include <iostream>
#include <deque>
#include <array>
using namespace std;
int main()
{
std::deque<int> d{ 1,2 };
//第一种格式用法
d.insert(d.begin() + 1, 3);//{1,3,2}
//第二种格式用法
d.insert(d.end(), 2, 5);//{1,3,2,5,5}
//第三种格式用法
std::array<int, 3>test{ 7,8,9 };
d.insert(d.end(), test.begin(), test.end());//{1,3,2,5,5,7,8,9}
//第四种格式用法
d.insert(d.end(), { 10,11 });//{1,3,2,5,5,7,8,9,10,11}
for (int i = 0; i < d.size(); i++) {
cout << d[i] << " ";
}
return 0;
}

emplace系列函数的优势:

#include <deque>
#include <iostream>
using namespace std;
class testDemo
{
public:
testDemo(int num) :num(num) {
std::cout << "调用构造函数" << endl;
}
testDemo(const testDemo& other) :num(other.num) {
std::cout << "调用拷贝构造函数" << endl;
}
testDemo(testDemo&& other) :num(other.num) {
std::cout << "调用移动构造函数" << endl;
}
testDemo& operator=(const testDemo& other);
private:
int num;
};
testDemo& testDemo::operator=(const testDemo& other) {
this->num = other.num;
return *this;
}
int main()
{
//emplace和insert
cout << "emplace:" << endl;
std::deque<testDemo> demo1;
demo1.emplace(demo1.begin(), 2);
cout << "insert:" << endl;
std::deque<testDemo> demo2;
demo2.insert(demo2.begin(), 2);
//emplace_front和push_front
cout << "emplace_front:" << endl;
std::deque<testDemo> demo3;
demo3.emplace_front(2);
cout << "push_front:" << endl;
std::deque<testDemo> demo4;
demo4.push_front(2);
//emplace_back()和push_back()
cout << "emplace_back:" << endl;
std::deque<testDemo> demo5;
demo5.emplace_back(2);
cout << "push_back:" << endl;
std::deque<testDemo> demo6;
demo6.push_back(2);
return 0;
}
output
emplace:
调用构造函数
insert:
调用构造函数
调用移动构造函数
emplace_front:
调用构造函数
push_front:
调用构造函数
调用移动构造函数
emplace_back:
调用构造函数
push_back:
调用构造函数
调用移动构造函数

最后

以上就是斯文摩托为你收集整理的STL序列容器详解之deque的全部内容,希望文章能够帮你解决STL序列容器详解之deque所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部