C++进阶之std::deque插入与删除效率(三百六十七)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者

新书发布:《Android系统多媒体进阶实战》🚀
优质专栏: Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏: 多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🌻1.前言

本篇目的:C++进阶之std::deque插入与删除效率

🌻2. C++进阶之std::deque插入与删除效率介绍

  1. 基本概念
    std::deque 是 C++ 标准库中的双端队列,支持在队列的两端进行插入和删除操作。与 std::vector 不同,std::deque 的元素存储在多个不连续的内存块中,这使得它在处理双端插入和删除时具有独特的效率优势。

  2. 尾部插入与删除
    std::deque 中,尾部的插入和删除操作非常高效,时间复杂度为 O(1)。这与 std::vector 类似,因为两者都能在不需要移动其他元素的情况下,直接在尾部添加或删除元素。

  3. 头部插入与删除
    std::deque 的一个优势是支持在头部进行插入和删除,且其时间复杂度为 O(1)。由于 std::deque 使用多个内存块来存储元素,在插入或删除时,不需要移动整个元素序列,只需操作相关内存块的指针。因此,头部插入和删除的性能较为高效。

  4. 内存块管理
    std::deque 内部采用分段存储,元素被分配到多个内存块中。当需要扩展时,它只需要分配新的内存块,而不是移动整个元素序列。这使得在两端进行插入和删除时不需要频繁地进行内存重分配和元素搬移,因此具有较高的插入删除效率。

  5. 中间位置插入与删除
    尽管 std::deque 在两端的插入和删除效率较高,但在中间位置插入和删除的效率较低,时间复杂度为 O(n)。这主要是因为中间位置的插入或删除需要调整多个内存块中的元素,可能会导致较高的开销。因此,std::deque 不适合频繁在中间位置进行操作。

  6. 整体性能
    std::deque 提供了高效的头部和尾部插入删除,但它的整体性能也会受到内存块管理的影响。在极端情况下,如果中间频繁进行插入和删除操作,性能可能会受到影响。因此,选择 std::deque 作为容器时,应根据应用场景来评估其性能优势。

  7. 扩展与缩减
    在扩展时,std::deque 不会像 std::vector 一样需要重新分配并复制整个数组,只需追加新的内存块。相反,当元素删除时,std::deque 会回收内存块,避免了不必要的内存浪费,保持了较好的内存管理。

  8. 适用场景
    std::deque 非常适合用于需要频繁在两端插入和删除元素的场景。例如,在实现双端队列、任务调度或缓存等应用时,std::deque 的高效插入和删除操作使其成为理想选择。

🌻3. 代码实例

🐓3.1 末尾插入与删除操作

  • 1.应用场景:
    std::deque 适用于 末尾插入与删除,并且其在末尾的插入和删除操作具有 常数时间复杂度。
    这种操作常见于队列或缓冲区的实现。
    在这里插入图片描述

  • 2.用法实例

#include <iostream>
#include <deque>
#include <chrono>

int main() {
    const int N = 100000;
    std::deque<int> dq;

    // 末尾插入
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; ++i) dq.push_back(i);
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "Deque 末尾插入时间: " 
              << std::chrono::duration<double>(end - start).count() << "s\n";

    // 末尾删除
    start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; ++i) dq.pop_back();
    end = std::chrono::high_resolution_clock::now();
    std::cout << "Deque 末尾删除时间: " 
              << std::chrono::duration<double>(end - start).count() << "s\n";

    return 0;
}

push_back() 和 pop_back() 在 std::deque 中是 常数时间操作,不受容器大小的影响。

🐓3.2 头部插入与删除操作

  • 1.应用场景:
    std::deque 适用于 头部插入与删除,但 其效率要优于 std::vector,在头部插入和删除时的时间复杂度为 O(1),而不是 std::vector 中的 O(N) 操作。
    这种操作常见于双端队列的应用,类似于环形缓冲区。
    在这里插入图片描述

  • 2.用法实例

#include <iostream>
#include <deque>
#include <chrono>

int main() {
    const int N = 100000;
    std::deque<int> dq;

    // 头部插入
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; ++i) dq.push_front(i);
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "Deque 头部插入时间: " 
              << std::chrono::duration<double>(end - start).count() << "s\n";

    // 头部删除
    start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; ++i) dq.pop_front();
    end = std::chrono::high_resolution_clock::now();
    std::cout << "Deque 头部删除时间: " 
              << std::chrono::duration<double>(end - start).count() << "s\n";

    return 0;
}

push_front() 和 pop_front() 在 std::deque 中是 常数时间操作,比 std::vector 在头部插入和删除的 O(N) 更高效。

🐓3.3 随机访问与插入中间元素的效率

  • 1.应用场景:
    std::deque 提供了 随机访问,并且可以在 两端插入或删除 元素时保持 O(1) 的复杂度,但在 中间插入或删除 时,仍然需要 O(N) 的时间复杂度。
    这种操作对于需要快速两端操作而中间操作不频繁的场景非常适用。
    在这里插入图片描述

  • 2.用法实例

#include <iostream>
#include <deque>
#include <chrono>

int main() {
    const int N = 100000;
    std::deque<int> dq(N, 0);  // 初始包含 N 个元素

    // 随机访问
    auto start = std::chrono::high_resolution_clock::now();
    volatile int x = dq[N / 2];  // 访问中间元素
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "Deque 随机访问时间: " 
              << std::chrono::duration<double>(end - start).count() << "s\n";

    // 中间插入
    start = std::chrono::high_resolution_clock::now();
    dq.insert(dq.begin() + N / 2, 42);  // 在中间插入元素
    end = std::chrono::high_resolution_clock::now();
    std::cout << "Deque 中间插入时间: " 
              << std::chrono::duration<double>(end - start).count() << "s\n";

    return 0;
}

operator[] O(1),可以直接进行随机访问。
中间插入和删除需要 移动元素,时间复杂度为 O(N)。

🐓3.4 用法总结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Android系统攻城狮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值