• 【C++ STL】-- deque与vector相比的优势与劣势


    目录

    deque容器

    与stack相比deque的优缺点:

    deque的迭代器

    deque的成员函数


    deque容器

    deque的相关文档

            deque与vector十分的相识。vector是单向开口的连续线性空间(单向扩容),deque则是一种双向开口的连续线性空间(双向扩容)。双向开口:可以在头尾两端分别做元素的插入和删除操作。区别就在此,vector当然也可以在头尾两端进行操作,但是其头部操作的效率奇差,无法被接受,如:stack与queue的容量适配器就在二者其中,选择deque(当然使用vector也可)

    vector与deque的差异:

    • deque允许于常数时间内对头端进行元素的插入或移除操作。
    • deque没有所谓的容量观念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并连接起来。

    与stack相比deque的优缺点:

    优势:

    • 头尾插入删除很方便

    劣势:

    • operator[]计算稍显复杂,大量使用,性能下降(下标需要经过计算)。
    • 中间插入删除效率不高(下标需要经过计算,并且需要挪动元素)。
    • 底层角度迭代器会很复杂。

    结论:

    • 头尾的插入删除deque非常适合,相比vector而言,很适合去做stack和queue的默认适配容器。
    • 中间插入删除少用deque,可以用:list(因为无需挪动元素)。
    • 随机访问多用vector(因为下标是确定的)。

    deque的迭代器

            需要注意,deque是连续的空间,但是这只是其逻辑上的,物理上并不是。所以在迭代器上维持其“整体连续”假象的工作,就落在迭代器中的operator++与operator--上了。

            首先,连续重要的就是能够指出分段空间在哪里,其次,它必须能够判断自己是否已经处于其所在的存储边缘,如果是,一旦前行或后退时就必须跳跃到下一个或上一个存储空间。

    1. // __deque_iterator的源码
    2. template <class T, class Ref, class Ptr, size_t BufSiz>
    3. struct __deque_iterator
    4. {
    5. typedef __deque_iterator iterator;
    6. typedef __deque_iteratorconst T&, const T*> const_iterator;
    7. static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }//buffer_size()用于确定缓冲区的大小
    8. typedef random_access_iterator_tag iterator_category;
    9. typedef T value_type;
    10. typedef Ptr pointer;
    11. typedef Ref reference;
    12. typedef size_t size_type; // size_t 是unsigned 类型,通常用来指明数组长度
    13. typedef ptrdiff_t difference_type; // ptrdiff_t 是 signed 整型,通常用来保存两个指针减法操作的结果
    14. typedef T** map_pointer;
    15. typedef __deque_iterator self;
    16. // 保持与容器的联结,是对某一个缓冲区而言的
    17. T* cur; // 此迭代器所指之缓冲区中的现行元素
    18. T* first; // 此迭代器所指之缓冲区的头
    19. T* last; // 此迭代器所指之缓冲区的尾(含备用空间)
    20. map_pointer node; // 指向管控中心
    21. ...
    22. }
    23. //deque_buf_size()全局函数
    24. inline size_t deque_buf_size(size_t n, size_t sz){
    25. return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
    26. }
    27. //定义:
    28. //1. 如果n不为0,传回n,表示buffer size由使用者自定。
    29. //2. 如果n为0,表示buffer size使用默认值,那么:
    30. // 如果sz不小于 512,返回1。
    31. // 如果sz(元素大小,sizeof(value_type))小于512,传回512/sz。

    1. void set_node(map_pointer new_node) {
    2. node = new_node;
    3. first = *new_node;
    4. last = first + difference_type(buffer_size());
    5. }
    6. reference operator*() const { return *cur; }
    7. pointer operator->() const { return &(operator*()); }
    8. difference_type operator-(const self& x) const {
    9. return difference_type(buffer_size()) * (node - x.node - 1) + (cur - first) + (x.last - x.cur);
    10. }
    11. self& operator++() {
    12. ++cur; //切换至下个元素
    13. if (cur == last) { //如果已达所在缓冲区的尾端,就切换至下一节点(亦即缓冲区)的第一个元素
    14. set_node(node + 1);
    15. cur = first;
    16. }
    17. return *this;
    18. }
    19. self operator++(int) { //后置式,标准写法
    20. self tmp = *this;
    21. ++*this;
    22. return tmp;
    23. }
    24. self& operator--() {
    25. if (cur == first) {//如果已达所在缓冲区的头端, 就切换至前一节点(亦即缓冲区)的最后一个元素
    26. set_node(node - 1);
    27. cur = last;
    28. }
    29. --cur; //切换至前一个元素
    30. return *this;
    31. }
    32. self operator--(int) { //后置式,标准写法
    33. self tmp = *this;
    34. --*this;
    35. return tmp;
    36. }
    37. // 以下实现随机存取。迭代器可以直接跳跃n个距离
    38. self& operator+=(difference_type n) {
    39. difference_type offset = n + (cur - first);
    40. if (offset >= 0 && offset < difference_type(buffer_size()))
    41. //标的位置在同一缓冲区内
    42. cur += n;
    43. else {
    44. //标的位置不在同一缓冲区内
    45. difference_type node_offset =
    46. offset > 0 ? offset / difference_type(buffer_size()) : -difference_type((-offset - 1) / buffer_size()) - 1;
    47. // 切换至正确的节点(亦即缓冲区)
    48. set_node(node + node_offset);
    49. // 切换至正确的元素
    50. cur = first + (offset - node_offset * difference_type(buffer_size()));
    51. }
    52. return *this;
    53. }
    54. self operator+(difference_type n) const {
    55. self tmp = *this;
    56. return tmp += n; //调用operator+=
    57. }
    58. //利用operator+=完成operator-=
    59. self& operator-=(difference_type n) { return *this += -n; }
    60. self operator-(difference_type n) const {
    61. self tmp = *this;
    62. return tmp -= n; //调用operator-=
    63. }
    64. //实现随机存取,迭代器可以直接跳跃n个距离
    65. reference operator[] (difference_type n) const { return * (*this + n);)}
    66. bool operator==(const self& x) const { return cur == x.cur; }
    67. bool operator!=(const self& x) const { return !(*this == x); }
    68. bool operator<(const self& x) const {
    69. return (node == x.node) ? (cur < x.cur) : (node < x.node);
    70. }

    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() 的区别是,该函数直接在容器尾部构造元素,省去了复制移动元素的过程。
  • 相关阅读:
    012 Spring Boot + Vue 电影购票系统
    Spring--getBean()与@Autowired的对比
    html网页设计与制作:基于html设计整套招聘网站求职前端模板页面 静态网页HTML代码 学生网页课程设计期末作业下载
    rabbitMq死信队列
    【第四阶段】kotlin语言的Map集合学习
    递归之谜:解析无限嵌套的美
    题目 1051: [编程入门]结构体之成绩统计2
    Docker (三): Docker架构及工作原理
    构造函数,原型,实例,类的关系整理
    深入理解MySQL——配置半同步复制
  • 原文地址:https://blog.csdn.net/weixin_64609308/article/details/127639609