当前位置:   article > 正文

【十八】【C++】deque双端队列简单使用和deque底层实现探究(部分代码)_c++ 双端队列dqueue

c++ 双端队列dqueue

deque简单使用

在C++中,双端队列(Double-Ended Queue, deque)是一种具有动态大小的序列容器,允许在两端快速插入和删除元素。与std::vector相比,std::deque提供了更加灵活的数据结构,特别是在需要频繁在序列的前端进行插入或删除操作时。

双端队列在<deque>头文件中定义,是标准模板库(STL)的一部分。

基本操作

插入和删除:

在前端插入(push_front)和删除(pop_front)元素。

在尾端插入(push_back)和删除(pop_back)元素。

访问元素:

访问首元素(front)和尾元素(back)。

随机访问(通过索引访问,如deque[index])。

容量:

检查双端队列是否为空(empty)。

获取双端队列中元素的数量(size)。

改变双端队列的大小(resize)。

迭代:

提供迭代器来遍历双端队列中的元素(正向迭代器和反向迭代器)。

  1. #include <iostream>
  2. #include <deque>
  3. int main() {
  4. std::deque<int> myDeque;
  5. // 在尾部插入元素
  6. myDeque.push_back(10);
  7. myDeque.push_back(20);
  8. // 在头部插入元素
  9. myDeque.push_front(5);
  10. myDeque.push_front(2);
  11. std::cout << "Deque elements: ";
  12. for(int elem : myDeque) {
  13. std::cout << elem << " ";
  14. }
  15. std::cout << "\n";
  16. // 访问第一个和最后一个元素
  17. std::cout << "First element: " << myDeque.front() << "\n";
  18. std::cout << "Last element: " << myDeque.back() << "\n";
  19. // 删除头部和尾部元素
  20. myDeque.pop_front();
  21. myDeque.pop_back();
  22. std::cout << "Deque size after pop operations: " << myDeque.size() << "\n";
  23. return 0;
  24. }

deque底层实现探究(部分代码)

__deque_buf_size函数(deque中单个缓冲区(buffer)可以容纳的元素数量)

 
  1. inline size_t __deque_buf_size(size_t n, size_t sz) {
  2. return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
  3. }

这个函数用于计算deque中单个缓冲区(buffer)可以容纳的元素数量。接受两个参数,n表示用户指定的元素数量,sz表示单个元素的大小。如果n不为0,就直接使用用户指定的数量。如果n为0,则根据元素的大小计算。如果单个元素大小小于512字节,那么一个缓冲区将分配足够的空间来存放至少512字节的元素(即512 / sz个元素),否则只存放一个元素。

__deque_iterator 迭代器

 
  1. template <class T, class Ref, class Ptr, size_t BufSiz>
  2. struct __deque_iterator {//deque迭代器
  3. typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
  4. typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
  5. static size_t buffer_size() {
  6. return __deque_buf_size(BufSiz, sizeof(T)); //结点的大小
  7. }
  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;
  13. typedef ptrdiff_t difference_type;
  14. typedef T** map_pointer;//结点指针
  15. typedef __deque_iterator self;
  16. T* cur;
  17. T* first;
  18. T* last;
  19. map_pointer node;//结点指针node
  20. __deque_iterator(T* x, map_pointer y)
  21. : cur(x), first(*y), last(*y + buffer_size()), node(y) {}
  22. __deque_iterator() : cur(0), first(0), last(0), node(0) {}
  23. __deque_iterator(const iterator& x)
  24. : cur(x.cur), first(x.first), last(x.last), node(x.node) {}
  25. reference operator*() const {
  26. return *cur;
  27. }
  28. pointer operator->() const {
  29. return &(operator*());
  30. }
  31. difference_type operator-(const self& x) const {
  32. return difference_type(buffer_size()) * (node - x.node - 1) +
  33. (cur - first) + (x.last - x.cur);
  34. }
  35. self& operator++() {
  36. ++cur;
  37. if (cur == last) {
  38. set_node(node + 1);
  39. cur = first;
  40. }
  41. return *this;
  42. }
  43. self operator++(int) {
  44. self tmp = *this;
  45. ++*this;
  46. return tmp;
  47. }
  48. self& operator--() {
  49. if (cur == first) {
  50. set_node(node - 1);
  51. cur = last;
  52. }
  53. --cur;
  54. return *this;
  55. }
  56. self operator--(int) {
  57. self tmp = *this;
  58. --*this;
  59. return tmp;
  60. }
  61. self& operator+=(difference_type n) {
  62. difference_type offset = n + (cur - first);
  63. if (offset >= 0 && offset < difference_type(buffer_size()))
  64. cur += n;
  65. else {
  66. difference_type node_offset =
  67. offset > 0 ? offset / difference_type(buffer_size())
  68. : -difference_type((-offset - 1) / buffer_size()) - 1;
  69. set_node(node + node_offset);
  70. cur = first + (offset - node_offset * difference_type(buffer_size()));
  71. }
  72. return *this;
  73. }
  74. self operator+(difference_type n) const {
  75. self tmp = *this;
  76. return tmp += n;
  77. }
  78. self& operator-=(difference_type n) {
  79. return *this += -n;
  80. }
  81. self operator-(difference_type n) const {
  82. self tmp = *this;
  83. return tmp -= n;
  84. }
  85. reference operator[](difference_type n) const {
  86. return *(*this + n);
  87. }
  88. bool operator==(const self& x) const {
  89. return cur == x.cur;
  90. }
  91. bool operator!=(const self& x) const {
  92. return !(*this == x);
  93. }
  94. bool operator<(const self& x) const {
  95. return (node == x.node) ? (cur < x.cur) : (node < x.node);
  96. }
  97. void set_node(map_pointer new_node) {
  98. node = new_node;
  99. first = *new_node;
  100. last = first + difference_type(buffer_size());
  101. }
  102. };

迭代器模版定义

 
  1. template <class T, class Ref, class Ptr, size_t BufSiz>
  2. struct __deque_iterator {//deque迭代器

定义了一个模板,T是数据类型,Ref是引用类型,Ptr是指针类型,BufSiz是缓冲区大小。

定义了一个结构体__deque_iterator,作为deque的迭代器。

 
  1. typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
  2. typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
  3. static size_t buffer_size() {
  4. return __deque_buf_size(BufSiz, sizeof(T)); //结点的大小
  5. }
  6. typedef random_access_iterator_tag iterator_category;
  7. typedef T value_type;
  8. typedef Ptr pointer;
  9. typedef Ref reference;
  10. typedef size_t size_type;
  11. typedef ptrdiff_t difference_type;
  12. typedef T** map_pointer;//结点指针
  13. typedef __deque_iterator self;
  1. typedef __deque_iterator<T, T&, T*, BufSiz>iterator;
  2. typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;

定义了迭代器和常量迭代器类型,分别用于修改和访问deque元素。

 
 
  1. static size_t buffer_size() {
  2. return __deque_buf_size(BufSiz, sizeof(T));
  3. }

定义了一个静态成员函数buffer_size,用来计算每个缓冲区的大小。

 
 
  1. typedef random_access_iterator_tag iterator_category;
  2. typedef T value_type;
  3. typedef Ptr pointer;
  4. typedef Ref reference;
  5. typedef size_t size_type;
  6. typedef ptrdiff_t difference_type;
  7. typedef T** map_pointer;

定义了iterator_categoryrandom_access_iterator_tag。这表示__deque_iterator是一个随机访问迭代器,支持像数组一样的快速随机访问。这个类型信息用于算法优化,让算法知道可以对这种迭代器进行随机访问。

定义了value_type为模板参数T,即迭代器指向的元素类型。这告诉我们迭代器遍历的容器中存储的数据类型。

定义了pointer为模板参数Ptr,即指向元素的指针类型。这是迭代器内部用来指向元素的指针类型。

定义了reference为模板参数Ref,即元素的引用类型。这允许迭代器通过解引用操作符返回元素的引用。

定义了size_typesize_t,这是一个无符号整数类型,用来表示大小或者数量。

定义了difference_typeptrdiff_t,这是一个有符号整数类型,用来表示两个迭代器之间的距离。它能够表示正数也能表示负数,用于计算两个迭代器之间的位置差距。

定义了map_pointer为指向指针的指针,即T**,这里的map_pointer用于指向控制结构中的一块内存,这块内存本身又存储了指向容器中某一块缓冲区的指针。在deque的实现中,这样的结构用于支持动态的缓冲区扩展和收缩,允许deque高效地在前端或后端添加或删除元素T*表示元素的指针,可以理解为数组,T**表示数组的指针,也就是数组的数组。

 
 
    typedef __deque_iterator self;

定义了一个类型别名self,表示迭代器自身的类型。

成员变量

 
  1. T* cur;
  2. T* first;
  3. T* last;
  4. map_pointer node;//结点指针node

定义了四个成员变量:cur是当前元素的指针,first是当前缓冲区第一个元素的指针,last是当前缓冲区最后一个元素之后的指针,node是指向当前缓冲区的指针。

构造函数

 
  1. __deque_iterator(T* x, map_pointer y)
  2. : cur(x), first(*y), last(*y + buffer_size()), node(y) {}
  3. __deque_iterator() : cur(0), first(0), last(0), node(0) {}
  4. __deque_iterator(const iterator& x)
  5. : cur(x.cur), first(x.first), last(x.last), node(x.node) {}
 
 
  1. __deque_iterator(T* x, map_pointer y)
  2. : cur(x), first(*y), last(*y + buffer_size()), node(y) {}

这是一个参数化构造函数,接收两个参数:xyx是一个指向元素的指针,y是一个指向指针的指针,即map_pointer,指向deque的一个缓冲区。构造函数使用这些参数初始化迭代器的内部状态:

cur初始化为x,表示当前迭代器指向的元素。

first通过解引用y获得,表示当前缓冲区的第一个元素的位置。

last也是通过解引用y并加上缓冲区大小(通过buffer_size()计算得到)来确定当前缓冲区最后一个元素的下一个位置。

node初始化为y,表示指向当前缓冲区的指针。

 
 
    __deque_iterator() : cur(0), first(0), last(0), node(0) {}

这是一个无参数构造函数,用于创建一个未指向任何元素的迭代器。所有内部指针,包括curfirstlastnode,都被初始化为nullptr(即0),表示这是一个“空”迭代器。

 
 
  1. __deque_iterator(const iterator& x)
  2. : cur(x.cur), first(x.first), last(x.last), node(x.node) {}

这是一个拷贝构造函数,用于创建一个新的迭代器,其状态是基于另一个同类型迭代器x的。这个构造函数简单地将x迭代器的内部状态(curfirstlastnode)复制到新创建的迭代器中,使得两个迭代器指向相同的元素和缓冲区。

引用操作符*和成员访问操作符->

 
  1. reference operator*() const {
  2. return *cur;
  3. }
  4. pointer operator->() const {
  5. return &(operator*());
  6. }

这个成员函数重载了解引用操作符*,使得可以通过迭代器直接访问其当前指向的元素。cur是一个指针,指向迭代器当前所指的元素。通过返回*cur,即返回当前元素的引用,允许我们读取或修改该元素。const关键字表示这个操作不会修改迭代器本身的状态。

这个成员函数重载了成员访问操作符->,使得可以通过迭代器访问其当前指向元素的成员。这里,它通过调用operator*()来获取当前元素的引用,然后返回这个元素的地址,从而允许通过->操作符来访问元素的成员。例如,如果迭代器指向的元素是一个结构体或类的实例,那么可以直接使用迭代器加->来访问该元素的成员函数或成员变量。const关键字同样表示这个操作不改变迭代器本身的状态。

迭代器相减操作

 
  1. difference_type operator-(const self& x) const {
  2. return difference_type(buffer_size()) * (node - x.node - 1) +
  3. (cur - first) + (x.last - x.cur);
  4. }

这段代码重载了减法操作符-,用于计算两个__deque_iterator迭代器之间的距离。这个操作符返回两个迭代器之间的元素数量差,其类型为difference_type,通常是ptrdiff_t,一个用于表示指针(或迭代器)间距离的整数类型。

difference_type(buffer_size()) * (node - x.node - 1):这部分计算了this迭代器和x迭代器之间跨越的完整缓冲区数量乘以每个缓冲区的大小。node - x.node - 1计算了两个迭代器间完整缓冲区的数量(不包括thisx所在的缓冲区)。

(cur - first):这部分计算了this迭代器在其当前缓冲区中的位置,即this迭代器当前指向的元素与当前缓冲区第一个元素之间的距离。

(x.last - x.cur):这部分计算了x迭代器在其所在缓冲区到缓冲区末尾的元素数量,实际上是计算x迭代器到其缓冲区结束位置的距离。

迭代器移动

 
  1. self& operator++() {
  2. ++cur;
  3. if (cur == last) {
  4. set_node(node + 1);
  5. cur = first;
  6. }
  7. return *this;
  8. }
  9. self operator++(int) {
  10. self tmp = *this;
  11. ++*this;
  12. return tmp;
  13. }
  14. self& operator--() {
  15. if (cur == first) {
  16. set_node(node - 1);
  17. cur = last;
  18. }
  19. --cur;
  20. return *this;
  21. }
  22. self operator--(int) {
  23. self tmp = *this;
  24. --*this;
  25. return tmp;
  26. }

这四个成员函数重载了前置和后置的自增(++)和自减(--)操作符,使得__deque_iterator可以向前或向后移动,这是迭代器的基本功能之一,允许遍历deque容器中的元素。

前置自增操作符++

 
 
  1. self& operator++() {
  2. ++cur;
  3. if (cur == last) {
  4. set_node(node + 1);
  5. cur = first;
  6. }
  7. return *this;
  8. }

++cur;首先将当前元素指针(cur)向前移动一个位置。

if (cur == last)检查cur是否已经到达当前缓冲区的末尾(注意last指向当前缓冲区最后一个元素之后的位置)。

如果是,set_node(node + 1);将迭代器移动到下一个缓冲区,同时cur更新为新缓冲区的第一个元素的位置(first)。

返回*this,即更新后的迭代器本身。

后置自增操作符++(int)

 
 
  1. self operator++(int) {
  2. self tmp = *this;
  3. ++*this;
  4. return tmp;
  5. }

创建当前迭代器的副本tmp

使用前置自增++*this;更新当前迭代器。

返回副本tmp,符合后置自增操作的语义,即返回增加前的值。

前置自减操作符--

 
 
  1. self& operator--() {
  2. if (cur == first) {
  3. set_node(node - 1);
  4. cur = last;
  5. }
  6. --cur;
  7. return *this;
  8. }

if (cur == first)检查cur是否已经是当前缓冲区的第一个元素。

如果是,则set_node(node - 1);将迭代器移动到前一个缓冲区,同时cur更新为该缓冲区的最后一个元素的位置(注意这里cur赋值为last,实际上应该是赋值为last - 1,因为last指向的是缓冲区末尾的下一个位置)。

--cur;然后将当前元素指针向后移动一个位置。

返回*this,即更新后的迭代器本身。

后置自减操作符--(int)

 
 
  1. self operator--(int) {
  2. self tmp = *this;
  3. --*this;
  4. return tmp;
  5. }

创建当前迭代器的副本tmp

使用前置自减--*this;更新当前迭代器。

返回副本tmp,符合后置自减操作的语义,即返回减少前的值。

迭代器+=n个位置操作

 
  1. self& operator+=(difference_type n) {
  2. difference_type offset = n + (cur - first);
  3. if (offset >= 0 && offset < difference_type(buffer_size()))
  4. cur += n;
  5. else {
  6. difference_type node_offset =
  7. offset > 0 ? offset / difference_type(buffer_size())
  8. : -difference_type((-offset - 1) / buffer_size()) - 1;
  9. set_node(node + node_offset);
  10. cur = first + (offset - node_offset * difference_type(buffer_size()));
  11. }
  12. return *this;
  13. }

这段代码重载了+=操作符,使得__deque_iterator迭代器可以在当前位置的基础上向前(或向后,如果n为负数)移动n个位置。这是随机访问迭代器的一个重要特性,允许迭代器进行非连续的跳跃式移动。

 
 
self& operator+=(difference_type n) {

这行定义了operator+=的函数签名,接收一个difference_type类型的参数n,表示要移动的元素数量,可以是正数也可以是负数。函数返回迭代器自身的引用,允许链式调用。

 
 
    difference_type offset = n + (cur - first);

计算offset,即从当前缓冲区的开始位置first到目标位置的总偏移量。如果n为正,表示向后移动;如果n为负,表示向前移动。

 
 
  1. if (offset >= 0 && offset < difference_type(buffer_size()))
  2. cur += n;

如果计算出的offset在当前缓冲区的范围内(即大于等于0且小于缓冲区的大小),直接调整当前元素指针cur即可达到目标位置。

 
 
  1. else {
  2. difference_type node_offset =
  3. offset > 0 ? offset / difference_type(buffer_size())
  4. : -difference_type((-offset - 1) / buffer_size()) - 1;

如果offset超出了当前缓冲区的范围,需要跨越一个或多个缓冲区。node_offset计算需要移动多少个缓冲区,正数表示向后跨越,负数表示向前跨越。

 
 
        set_node(node + node_offset);

调用set_node函数,根据计算出的node_offset移动到新的缓冲区。

 
 
        cur = first + (offset - node_offset * difference_type(buffer_size()));

在新的缓冲区中,计算cur的正确位置。offset - node_offset * difference_type(buffer_size())计算在最终缓冲区中的偏移量。

 
 
  1. return *this;
  2. }

返回迭代器自身的引用,支持链式操作。

迭代器+、-=、-符号重载

 
  1. self operator+(difference_type n) const {
  2. self tmp = *this;
  3. return tmp += n;
  4. }
  5. self& operator-=(difference_type n) {
  6. return *this += -n;
  7. }
  8. self operator-(difference_type n) const {
  9. self tmp = *this;
  10. return tmp -= n;
  11. }

self operator+(difference_type n) const

创建当前迭代器的一个副本tmp

使用之前定义的operator+=tmp上加上n个位置。

返回修改后的副本tmp。这个操作不会改变原始迭代器的状态,因为它是在副本上进行的。

self& operator-=(difference_type n)

利用已经定义的operator+=实现减法操作,通过向+=传递-n作为参数。

这意味着-=操作实质上是将迭代器向后(或向前,如果n为负数)移动n个位置。

返回当前迭代器的引用,允许链式操作。

self operator-(difference_type n) const

与加法操作符类似,首先创建当前迭代器的一个副本tmp

使用operator-=tmp上减去n个位置。

返回修改后的副本tmp。这个操作也是不会改变原始迭代器的状态,因为它是在副本上进行的。

迭代器[]符号重载

 
  1. reference operator[](difference_type n) const {
  2. return *(*this + n);
  3. }

这段代码重载了下标操作符[],使得__deque_iterator可以通过下标访问的方式直接访问到相对于当前迭代器位置n个元素的位置处的元素。

*this + n首先使用之前定义的加法操作符+来创建一个新的迭代器,这个新迭代器位于当前迭代器之后(或之前,如果n为负数)n个位置。

*操作符随后被用于这个新的迭代器,通过解引用操作返回位于该位置的元素的引用。

因此,operator[]允许通过类似数组的语法直接访问deque中的元素,即使deque的物理存储可能是非连续的。

迭代器==、!=、<符号重载

 
  1. bool operator==(const self& x) const {
  2. return cur == x.cur;
  3. }
  4. bool operator!=(const self& x) const {
  5. return !(*this == x);
  6. }
  7. bool operator<(const self& x) const {
  8. return (node == x.node) ? (cur < x.cur) : (node < x.node);
  9. }

bool operator==(const self& x) const

比较两个迭代器是否相等。如果两个迭代器指向deque中相同的元素(即它们的cur成员,也就是当前元素的指针,相同),则认为这两个迭代器相等,返回true;否则返回false

这里没有比较node,因为如果两个迭代器的cur相同,则它们必定在同一个缓冲区中,即node也相同。

bool operator!=(const self& x) const

通过调用已经定义的等于操作符==来判断两个迭代器是否不相等。如果*this == x返回false,则表示两个迭代器不指向同一个元素,因此这里返回true表明它们不相等;反之亦然。

这是等于操作符的直接逻辑反转。

bool operator<(const self& x) const

用于比较两个迭代器的顺序。首先判断两个迭代器是否位于同一个缓冲区(即它们的node相同);如果是,那么通过比较它们的cur来判断顺序。

如果不在同一个缓冲区,那么通过比较它们的node来判断哪个迭代器指向的元素在deque中的位置更前。

这允许对迭代器进行排序,从而可以在算法中使用迭代器来比较元素位置,如在二分查找或其他需要元素顺序信息的算法中。

set_node函数

 
  1. void set_node(map_pointer new_node) {
  2. node = new_node;
  3. first = *new_node;
  4. last = first + difference_type(buffer_size());
  5. }

这个成员函数set_node__deque_iterator结构体中的一个辅助函数,用于设置迭代器以指向新的缓冲区。当迭代器需要跨越到另一个缓冲区时,这个函数被调用来更新迭代器的状态,确保它正确地指向新的缓冲区内的元素。

new_node是一个指向新缓冲区的指针的指针(map_pointer类型),也就是deque的控制结构中的一个节点。

更新node成员变量为新缓冲区的指针,node现在指向新的缓冲区。

通过解引用new_node获取新缓冲区的首地址,然后将这个地址赋值给firstfirst现在指向新缓冲区中的第一个元素。

计算新缓冲区的最后一个元素的下一个位置,并将这个位置的指针赋值给last。这里使用buffer_size()函数来获取缓冲区的大小(即可以存储的元素数量),然后将这个大小加到first上,从而得到last的位置。这里的buffer_size()函数返回的是根据deque的元素类型和可能的用户指定的缓冲区大小参数BufSiz计算出的缓冲区大小。

deque类(部分代码)

成员变量

 
  1. iterator start;
  2. iterator finish;
  3. map_pointer map;
  4. size_type map_size;

iterator start;

start是一个迭代器,指向deque中的第一个缓冲区位置。这个迭代器使得可以从deque的前端开始访问元素。

iterator finish;

finish是一个迭代器,指向deque中最后一个缓冲区位置。这个设计是为了提供一种统一的方式来表示容器的末尾,类似于C++标准库中其他容器的end迭代器。

map_pointer map;

map是一个指向指针数组的指针,这个指针数组中的每个指针都指向deque的一个缓冲区。deque的实现通常涉及多个这样的缓冲区,每个缓冲区存储容器的一部分元素,而map则管理这些缓冲区的指针,从而允许随机访问deque中的任意元素。

size_type map_size;

map_size表示map指针数组的大小,也就是当前deque可以使用的缓冲区数量。这个数值反映了deque的容量在空间布局上的一个方面,即它能够管理多少个缓冲区。

deque的begin、end、rbegin、rend

 
  1. iterator begin() {
  2. return start;
  3. }
  4. iterator end() {
  5. return finish;
  6. }
  7. const_iterator begin() const {
  8. return start;
  9. }
  10. const_iterator end() const {
  11. return finish;
  12. }
  13. reverse_iterator rbegin() {
  14. return reverse_iterator(finish);
  15. }
  16. reverse_iterator rend() {
  17. return reverse_iterator(start);
  18. }
  19. const_reverse_iterator rbegin() const {
  20. return const_reverse_iterator(finish);
  21. }
  22. const_reverse_iterator rend() const {
  23. return const_reverse_iterator(start);
  24. }

deque[]

 
  1. reference operator[](size_type n) {
  2. return start[difference_type(n)];
  3. }
  4. const_reference operator[](size_type n) const {
  5. return start[difference_type(n)];
  6. }

start是第一个缓冲区的位置,对这个缓冲区的cur副本进行+=n个位置操作,而原cur不会改变,计算出来的第n个位置作为返回值。

deque的front、back

 
  1. reference front() {
  2. return *start;
  3. }
  4. reference back() {
  5. iterator tmp = finish;
  6. --tmp;
  7. return *tmp;
  8. }
  9. const_reference front() const {
  10. return *start;
  11. }
  12. const_reference back() const {
  13. const_iterator tmp = finish;
  14. --tmp;
  15. return *tmp;
  16. }

deque的size()、max_size()、empty()

 
  1. size_type size() const {
  2. return finish - start;;
  3. }
  4. bool empty() const {
  5. return finish == start;
  6. }

deque的头插尾插头删尾删

 
  1. void push_back(const value_type& t) {
  2. if (finish.cur != finish.last - 1) {
  3. construct(finish.cur, t);
  4. ++finish.cur;
  5. } else
  6. push_back_aux(t);
  7. }
  8. void push_front(const value_type& t) {
  9. if (start.cur != start.first) {
  10. construct(start.cur - 1, t);
  11. --start.cur;
  12. } else
  13. push_front_aux(t);
  14. }
  15. void pop_back() {
  16. if (finish.cur != finish.first) {
  17. --finish.cur;
  18. destroy(finish.cur);
  19. } else
  20. pop_back_aux();
  21. }
  22. void pop_front() {
  23. if (start.cur != start.last - 1) {
  24. destroy(start.cur);
  25. ++start.cur;
  26. } else
  27. pop_front_aux();
  28. }

push_back函数

当尾部当前缓冲区(finish.cur)没有达到其最后一个元素的位置(finish.last - 1)时,直接在尾部当前位置构造新元素t并将finish.cur向后移动一个位置,以指向新的末尾。

如果尾部当前缓冲区已满(finish.cur == finish.last - 1),则调用push_back_aux(t),一个辅助函数来处理在新的缓冲区中添加元素的情况。

push_front函数

当头部当前缓冲区(start.cur)不在其第一个元素的位置时(即有空间在当前缓冲区的前面插入新元素),在start.cur前一个位置构造新元素t并将start.cur向前移动一个位置。

如果头部当前缓冲区没有空间(start.cur == start.first),则调用push_front_aux(t),一个辅助函数来处理在新的缓冲区中添加元素的情况。

pop_back函数

当尾部当前缓冲区(finish.cur)不在其第一个元素的位置时(即尾部缓冲区中有至少两个元素可以移除),将finish.cur向前移动一个位置并销毁该位置上的元素。

如果尾部当前缓冲区只有一个元素时(finish.cur == finish.first),则调用pop_back_aux(),一个辅助函数来处理跨缓冲区移除尾部元素的情况。

pop_front函数

当头部当前缓冲区(start.cur)不在其最后一个元素的位置时(即头部缓冲区中有至少两个元素可以移除),销毁start.cur位置上的元素并将start.cur向后移动一个位置。

如果头部当前缓冲区只有一个元素时(start.cur == start.last - 1),则调用pop_front_aux(),一个辅助函数来处理跨缓冲区移除头部元素的情况。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/975221
推荐阅读
相关标签
  

闽ICP备14008679号