C++STL 系列(三):deque 容器详解与示例

文章目录

  • [deque 基本概念](#deque 基本概念)
  • [deque 构造函数](#deque 构造函数)
  • deque赋值操作
  • [deque 大小操作](#deque 大小操作)
  • [deque 插入和删除](#deque 插入和删除)
  • [deque 数据存取](#deque 数据存取)
  • [deque 排序](#deque 排序)

仓库链接
本仓库提供STL相关每一篇文章的完整可运行示例代码。

bash 复制代码
git clone https://github.com/MaikieMaiky/cpp_STL.git

deque 基本概念

Double-ended queue (Qw) 双端队列

deque读音与deck一致

功能:

  • 双端数组,可对头部/尾部执行插入删除动作

deque与vector区别:

  • vector头插效率低
  • deque头插效率高
  • vector访问更快
cpp 复制代码
               front()                  back()
              ----------------------------------
push_front()                              ----->    push_back()
                1    2    _    3    4    5  
pop_front()     ^          ^             ^      ^   pop_back()
              --|----------|-------------|------|---
v.rend() v.begin()  insert()  v.begin()  v.end()

内部工作原理:

  • deque内部有一个中控器,维护每段缓冲区的内容,缓冲区放真实数据
  • 中控器维护的是每个缓冲区的地址,使得使用时看起来像一片连续的内存空间
  • 每个缓冲区都是分开的,需要通过地址去查找,自然访问的速度没有连续的vector快
cpp 复制代码
(中控器)
|    |  --->[            ele ele ele] (头插方便)
|0x01|--|
|0x02|----->[ele ele ele ele ele ele]
|0x02|--|
|    |  --->[ele ele ele            ] (尾插方便)
|    |
(二次寻址,访问元素自然慢)
  • deque容器的迭代器也支持随机访问
  • deque的成员函数和vector基本一样,使用也基本一样,了解一下即可

deque 构造函数

打印容器使用const限制已读

迭代器使用const_iterater

原型:

  • deque<T> deq; // 默认构造形式

  • deque(beg, end); // 构造函数将[beg, end)区间中的元素拷贝给本身。(迭代器区间)

  • deque(n, elem); // 构造函数将n个elem拷贝给本身。

  • deque(const deque &deq); // 拷贝构造函数

  • 示例

    cpp 复制代码
    // deque的构造函数
    /**
     * deque<T> deq;                        // 默认构造形式
     * deque(beg, end);                      // 构造函数将[beg, end)区间中的元素拷贝给本身。(迭代器区间)
     * deque(n, elem);                       // 构造函数将n个elem拷贝给本身。
     * deque(const deque &deq);              // 拷贝构造函数
     */
    #include <iostream>
    #include <deque>
    
    using namespace std;
    
    // 使用const deque保证只读不修改
    void print_deque(const deque<int>& d)
    {
        // 因为只读不修改,因此需要使用const_iterator
        for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        // 1. 默认构造
        deque<int> d1;
        for (int i = 0; i < 10; i++)
        {
            d1.push_back(i);
        }
        cout << "d1 = ";
        print_deque(d1);
    
        // 2. 迭代器区间拷贝
        deque<int> d2(d1.begin(), d1.end());
        cout << "d2 = ";
        print_deque(d2);
    
        // 3. 将n个elem拷贝给本身。
        deque<int> d3(10, 66);
        cout << "d3 = ";
        print_deque(d3);
    
        // 4. 拷贝构造
        deque<int> d4(d3);
        cout << "d4 = ";
        print_deque(d4);
    }
    
    int main()
    {
        test0();
        return 0;
    }
  • 这里新增一个知识点,打印deque只需要读而不用改,因此可以使用const来约束输入的deque保证只读,并且配合使用const_iterator来实现


deque赋值操作

原型:

  • deque& operator=(const deque &deq); // 重载=操作符

  • assign(beg, end); // 将[beg, end)区间中的数据拷贝赋值给本身(迭代器区间)

  • assign(n, elem); // 将n个elem拷贝赋值给本身

  • 示例

    cpp 复制代码
    // deque的赋值操作
    /**
     * deque& operator=(const deque &deq);            // 重载=操作符
     * assign(beg, end);                              // 将[beg, end)区间中的数据拷贝赋值给本身(迭代器区间)
     * assign(n, elem);                               // 将n个elem拷贝赋值给本身
     */
    #include <iostream>
    #include <deque>
    
    using namespace std;
    
    void print_deque(const deque<int>& d)
    {
        for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        deque<int> d1;
        for (int i = 0; i < 10; i++)
        {
            d1.push_back(i);
        }
        cout << "d1 = ";
        print_deque(d1);
    
        // 1. 重载=操作符
        deque<int> d2;
        d2 = d1;
        cout << "d2 = ";
        print_deque(d2);
        
        // 2. 将[beg, end)区间中的数据拷贝赋值给本身(迭代器区间)
        deque<int> d3;
        d3.assign(d1.begin(), d1.end());
        cout << "d3 = ";
        print_deque(d3);
        
        // 3. 将n个elem拷贝赋值给本身
        deque<int> d4;
        d4.assign(10, 66);
        cout << "d4 = ";
        print_deque(d4);
    }
    
    int main()
    {
        test0();
        return 0;
    }

deque 大小操作

deque和vector有一点不同:无capacity,只有size,deque可以无限开辟缓冲区,中控器加地址即可,不需要提前分配大块

原型:

  • size(); // 返回容器中元素的个数

  • empty(); // 判断容器是否为空

  • resize(num); // 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。

  • resize(num, elem); // 重新指定容器的长度为num,若容器变长,则以elem值填充新位置。

  • 示例

    cpp 复制代码
    // deque的大小操作
    /**
     * size();                               // 返回容器中元素的个数
     * empty();                              // 判断容器是否为空
     * resize(num);                          // 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
     * resize(num, elem);                    // 重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
     */
    #include <iostream>
    #include <deque>
    
    using namespace std;
    
    void print_deque(const deque<int>& d)
    {
        for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        deque<int> d1;
        for (int i = 0; i < 10; i++)
        {
            d1.push_back(i);
        }
        cout << "d1 = ";
        print_deque(d1);
    
        // 1. 返回容器中元素的个数
        cout << "d1.size() = " << d1.size() << endl;
    
        // 2. 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
        d1.resize(15);
        cout << "d1 = ";
        print_deque(d1);
        cout << "d1.size() = " << d1.size() << endl;
    
        // 3. 重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
        d1.resize(20, 22);
        cout << "d1 = ";
        print_deque(d1);
        cout << "d1.size() = " << d1.size() << endl;
    
        // 4. 判断容器是否为空
        if (d1.empty())
        {
            cout << "d1 is empty" << endl;
        }
        else
        {
            cout << "d1 is not empty" << endl;
        }
    }
    
    int main()
    {
        test0();
        return 0;
    }

deque 插入和删除

原型:

两端插入/删除

  • push_back(elem); // 在容器尾部添加一个数据
  • push_front(elem); // 在容器头部插入一个数据
  • pop_back(); // 删除容器最后一个数据
  • pop_front(); // 删除容器第一个数据

指定位置(pos处需要输入迭代器)

  • insert(pos, elem); // 在pos位置插入一个elem元素的拷贝,返回新数据的位置。

  • insert(pos, n, elem); // 在pos位置插入n个elem数据,无返回值。

  • insert(pos, beg, end); // 在pos位置插入[beg, end)区间的数据,无返回值。

  • erase(pos); // 删除pos位置的数据,返回下一个数据的位置。

  • erase(beg, end); // 删除[beg, end)区间的数据,返回下一个数据的位置。

  • clear(); // 清空容器中的所有数据

  • 示例

    cpp 复制代码
    // deque的插入和删除
    /**
     * 两端插入/删除
     * push_back(elem);                          // 在容器尾部添加一个数据
     * push_front(elem);                         // 在容器头部插入一个数据
     * pop_back();                               // 删除容器最后一个数据
     * pop_front();                              // 删除容器第一个数据
     *
     * 指定位置操作(pos处需要输入迭代器)
     * insert(pos, elem);                        // 在pos位置插入一个elem元素的拷贝,返回新数据的位置。
     * insert(pos, n, elem);                     // 在pos位置插入n个elem数据,无返回值。
     * insert(pos, beg, end);                    // 在pos位置插入[beg, end)区间的数据,无返回值。
     * erase(pos);                               // 删除pos位置的数据,返回下一个数据的位置。
     * erase(beg, end);                          // 删除[beg, end)区间的数据,返回下一个数据的位置。
     * clear();                                  // 清空容器中的所有数据
     */
    #include <iostream>
    #include <deque>
    
    using namespace std;
    
    void print_deque(const deque<int>& d)
    {
        for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        deque<int> d1;
        // 尾插
        d1.push_back(10);
        d1.push_back(20);
        d1.push_back(30);
        // 头插
        d1.push_front(100);
        d1.push_front(200);
        d1.push_front(300);
        cout << "d1 = ";
        print_deque(d1);
    
        // 尾删
        d1.pop_back();
        // 头删
        d1.pop_front();
        cout << "d1 = ";
        print_deque(d1);
    
        // 指定位置插入
        d1.insert(d1.begin() + 1, 1000);
        cout << "d1 = ";
        print_deque(d1);
    
        // 指定位置插入n个elem数据
        d1.insert(d1.end() - 1, 2, 2000);
        cout << "d1 = ";
        print_deque(d1);
    
        // 指定位置插入[beg, end)区间的数据
        deque<int> d2;
        d2.push_back(1);
        d2.push_back(2);
        d2.push_back(3);
        d1.insert(d1.begin() + 1, d2.begin(), d2.end());
        cout << "d1 = ";
        print_deque(d1);
    
        // 指定位置删除
        d1.erase(d1.begin());
        cout << "d1 = ";
        print_deque(d1);
    
        // 删除指定位置的元素
        d1.erase(d1.begin() + 1);
        cout << "d1 = ";
        print_deque(d1);
    
        // 删除指定位置的元素
        d1.erase(d1.begin() + 1, d1.begin() + 3);
        cout << "d1 = ";
        print_deque(d1);
    
        // 清空容器中的所有数据
        d1.clear();
        cout << "d1 = ";
        print_deque(d1);
    }
    
    int main()
    {
        test0();
        return 0;
    }

deque 数据存取

原型:

  • at(idx); // 返回索引idx所指的数据

  • operator[]; // 返回索引idx所指的数据

  • front(); // 返回首元素

  • back(); // 返回尾元素

  • 示例

    cpp 复制代码
    // deque的数据存取
    /**
     * at(idx);                                 // 返回索引idx所指的数据
     * operator[];                              // 返回索引idx所指的数据
     * front();                                 // 返回首元素
     * back();                                  // 返回尾元素
     */
    #include <iostream>
    #include <deque>
    
    using namespace std;
    
    void test0()
    {
        deque<int> d;
        d.push_back(10);
        d.push_back(20);
        d.push_back(30);
        d.push_front(100);
        d.push_front(200);
        d.push_front(300);
    
        cout << "d = ";
        for (int i = 0; i < d.size(); i++)
        {
            cout << d.at(i) << " ";
        }
        cout << endl;
    
        cout << "d = ";
        for (int i = 0; i < d.size(); i++)
        {
            cout << d[i] << " ";
        }
        cout << endl;
    
        cout << "d.front() = " << d.front() << endl;
        cout << "d.back() = " << d.back() << endl;
    }
    
    int main()
    {
        test0();
        return 0;
    }

deque 排序

原型:

  • sort(iterator beg, iterator end); // 对[beg, end)区间内的元素进行排序
    需要包含

sort排序支持所有随机访问迭代器的容器(eg. vector),都可以利用sort算法直接进行排序

  • 示例

    cpp 复制代码
    // deque的排序
    /**
     * sort(iterator beg, iterator end); // 对[beg, end)区间内的元素进行排序
     */
    #include <iostream>
    #include <deque>
    #include <algorithm>
    
    using namespace std;
    
    void print_deque(const deque<int>& d)
    {
        for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        deque<int> d;
        d.push_back(10);
        d.push_back(20);
        d.push_back(30);
        d.push_front(100);
        d.push_front(200);
        d.push_front(300);
        cout << "d = ";
        print_deque(d);
    
        // 排序 默认升序
        sort(d.begin(), d.end());
        cout << "d = ";
        print_deque(d);
    }
    
    int main()
    {
        test0();
        return 0;
    }
相关推荐
南境十里·墨染春水1 小时前
线程池学习(三) 实现固定线程池
开发语言·c++·学习
橘子海全栈攻城狮1 小时前
【最新源码】基于springboot的快递物流平台的设计与实现C102
java·开发语言·spring boot·后端·spring·web安全
之歆1 小时前
DAY_24JavaScript 面向对象深度全解:Object、构造函数与 this 系统指南(上)
开发语言·前端·javascript·原型模式
nazisami1 小时前
初识AVL树
c++·面向对象·avl树
sakiko_1 小时前
Swift报错合集(Xcode编译器)
开发语言·swiftui·xcode·swift·uikit
海盗12341 小时前
C#中使用MiniExcel 快速入门:读写 .xlsx 文件
开发语言·windows·c#
XMYX-01 小时前
29 - Go time 时间模块详解:时间处理、定时控制与底层设计
开发语言·golang
小小de风呀1 小时前
de风——【从零开始学C++】(七):string类详解
开发语言·c++·算法
丘比特惩罚陆1 小时前
制作类似aimlab的测试手速反应力的小游戏
开发语言·javascript·visual studio