zoukankan      html  css  js  c++  java
  • deque

    deque 中控器

    由于 deque 是分段连续线性空间的,为了用户方便操作,所以它对外的接口类似于连续空间。

    为了管理这些分段空间 deque 容器引入了一种中控器 map,map 是一块连续的空间,其中每个元素是指向缓冲区的指针,缓冲区才是 deque 存储数据的主体。

    _Tp** _M_map;   //@ map 是小块连续空间,其内的每个元素都是一个指针(节点),指向一块缓冲区
    size_t _M_map_size;  //@ map 内可以容纳多个指针
    

    deque 的迭代器

    deque 迭代器的功能:

    • 必须知道缓冲区的位置。
    • 能够判断是否处于其所在缓冲区的边界。
    • 能够知道其所在缓冲区当前所指位置的元素。
    template <class _Tp, class _Ref, class _Ptr>
    struct _Deque_iterator {
     //@ ... 
      _Tp* _M_cur;   //@ 迭代器指向缓冲区的当前元素
      _Tp* _M_first; //@ 迭代器指向缓冲区的头部
      _Tp* _M_last;  //@ 迭代器指向缓冲区的尾部
      _Map_pointer _M_node;  //@ 迭代器指向 map 的 node
      //@ ...
    };
    

    为了实现能够随机访问,deque的中控器、缓冲区和迭代器之间的相互关系如下图所示:

    // Note: this function is simply a kludge to work around several compilers'
    //  bugs in handling constant expressions.
    //@ 决定缓冲区大小的函数,全局函数,当 __size 小于 512 bytes,就返回 512 / __size
    inline size_t __deque_buf_size(size_t __size) {
      return __size < 512 ? size_t(512 / __size) : size_t(1);
    }
    
    //@ deque 迭代器的结构
    template <class _Tp, class _Ref, class _Ptr>
    struct _Deque_iterator {
      typedef _Deque_iterator<_Tp, _Tp&, _Tp*>             iterator;
      typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
      static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }
    
      typedef random_access_iterator_tag iterator_category;  // Random access iterator
      typedef _Tp value_type;
      typedef _Ptr pointer;
      typedef _Ref reference;
      typedef size_t size_type;
      typedef ptrdiff_t difference_type;
      typedef _Tp** _Map_pointer;
    
      typedef _Deque_iterator _Self;
    
      _Tp* _M_cur;   // 迭代器指向缓冲区的当前元素
      _Tp* _M_first; // 迭代器指向缓冲区的头部
      _Tp* _M_last;  // 迭代器指向缓冲区的尾部
      _Map_pointer _M_node;  // 迭代器指向 map 的 node
    
      _Deque_iterator(_Tp* __x, _Map_pointer __y) 
        : _M_cur(__x), _M_first(*__y),
          _M_last(*__y + _S_buffer_size()), _M_node(__y) {}
      _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {}
      _Deque_iterator(const iterator& __x)
        : _M_cur(__x._M_cur), _M_first(__x._M_first), 
          _M_last(__x._M_last), _M_node(__x._M_node) {}
    
      reference operator*() const { return *_M_cur; }  //@ 获取迭代器当前指向元素
    #ifndef __SGI_STL_NO_ARROW_OPERATOR
      pointer operator->() const { return _M_cur; }
    #endif /* __SGI_STL_NO_ARROW_OPERATOR */
    
      //@ 迭代器 operator-,返回两个迭代器之间的距离
      difference_type operator-(const _Self& __x) const {
        return difference_type(_S_buffer_size()) * (_M_node - __x._M_node - 1) +
          (_M_cur - _M_first) + (__x._M_last - __x._M_cur);
      }
    
      //@ 迭代器前置式operator++
      _Self& operator++() {
        ++_M_cur;  //@ 先移动下一个元素
        if (_M_cur == _M_last) { //@ 如果已到达所在缓冲区的尾端
          _M_set_node(_M_node + 1); //2 就切换到下一节点(下一个缓冲区)
          _M_cur = _M_first;   //@ 指向下一个缓冲区的第一个元素
        }
        return *this; 
      }
      
      //@ 迭代器后置式operator++
      _Self operator++(int)  {
        _Self __tmp = *this;
        ++*this;
        return __tmp;
      }
    
      //@ 迭代器前置式operator--
      _Self& operator--() {
        if (_M_cur == _M_first) {  //@ 如果已到达所在缓冲区的头端
          _M_set_node(_M_node - 1); //@ 就切换到上一个节点(上一个缓冲区)
          _M_cur = _M_last;  //@ 指向上一个缓冲区的最后一个元素
        }
        --_M_cur;  //@ 移动上一个元素
        return *this;
      }
      
      //@ 迭代器后置式operator--
      _Self operator--(int) {
        _Self __tmp = *this;
        --*this;
        return __tmp;
      }
    
      //@ 迭代器可以直接移动 n 个距离
      _Self& operator+=(difference_type __n)
      {
        difference_type __offset = __n + (_M_cur - _M_first);
        if (__offset >= 0 && __offset < difference_type(_S_buffer_size()))
          _M_cur += __n;  //@ 目标位置在同一缓冲区内
        else {  //@ 标记的位置不在同一缓冲区内
          difference_type __node_offset =
            __offset > 0 ? __offset / difference_type(_S_buffer_size())
                       : -difference_type((-__offset - 1) / _S_buffer_size()) - 1;
          _M_set_node(_M_node + __node_offset);   //@ 切换到正确的节点(缓冲区) 
          _M_cur = _M_first +   //@ 切换到正确的元素
            (__offset - __node_offset * difference_type(_S_buffer_size()));
        }
        return *this;
      }
    
      //@ 调用 operator+=
      _Self operator+(difference_type __n) const
      {
        _Self __tmp = *this;
        return __tmp += __n;
      }
    
      //@ 调用 operator+=
      _Self& operator-=(difference_type __n) { return *this += -__n; }
     
      //@ 调用 operator-=
      _Self operator-(difference_type __n) const {
        _Self __tmp = *this;
        return __tmp -= __n;
      }
    
      //@ 迭代器可以直接移动到 n 个距离,获取该位置的元素
      reference operator[](difference_type __n) const { return *(*this + __n); }
      
      //@ 两个容器比较
      bool operator==(const _Self& __x) const { return _M_cur == __x._M_cur; }
      bool operator!=(const _Self& __x) const { return !(*this == __x); }
      bool operator<(const _Self& __x) const {
        return (_M_node == __x._M_node) ? 
          (_M_cur < __x._M_cur) : (_M_node < __x._M_node);
      }
      bool operator>(const _Self& __x) const  { return __x < *this; }
      bool operator<=(const _Self& __x) const { return !(__x < *this); }
      bool operator>=(const _Self& __x) const { return !(*this < __x); }
    
      //@ 调用 set_node() 移动下一个缓冲区
      void _M_set_node(_Map_pointer __new_node) {
        _M_node = __new_node;
        _M_first = *__new_node;
        _M_last = _M_first + difference_type(_S_buffer_size());
      }
    };
    

    deque 的数据结构

    deque 容器具有维护 map 和迭代器的功能,deque 定义的两个迭代器分别是 start 和 finish,分别指向第一个缓冲区的第一个元素和最后一个缓冲区的最后一个元素的下一个位置。

    template <class _Tp, class _Alloc>
    class _Deque_base {
    public:
      typedef _Deque_iterator<_Tp,_Tp&,_Tp*>             iterator;
      typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
    
      typedef _Alloc allocator_type;
      allocator_type get_allocator() const { return allocator_type(); }
    
      _Deque_base(const allocator_type&, size_t __num_elements)
        : _M_map(0), _M_map_size(0),  _M_start(), _M_finish() {
        _M_initialize_map(__num_elements);
      }
      _Deque_base(const allocator_type&)
        : _M_map(0), _M_map_size(0),  _M_start(), _M_finish() {}
      ~_Deque_base();    
    
    protected:
      void _M_initialize_map(size_t);
      void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);
      void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish);
      enum { _S_initial_map_size = 8 };
    
    protected:
      _Tp** _M_map;
      size_t _M_map_size;  
      iterator _M_start;
      iterator _M_finish;
    
      //@ 专属的空间配置器,每次配置一个元素大小 
      typedef simple_alloc<_Tp, _Alloc>  _Node_alloc_type; 
      typedef simple_alloc<_Tp*, _Alloc> _Map_alloc_type;
    
      _Tp* _M_allocate_node()  //@ deque 内存分配
        { return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp))); }
      void _M_deallocate_node(_Tp* __p) //@ deque 内存释放
        { _Node_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp))); }
      _Tp** _M_allocate_map(size_t __n) 
        { return _Map_alloc_type::allocate(__n); }
      void _M_deallocate_map(_Tp** __p, size_t __n) 
        { _Map_alloc_type::deallocate(__p, __n); }
    };
    

    deque 的构造函数和析构函数

      explicit deque(const allocator_type& __a = allocator_type()) 
        : _Base(__a, 0) {}
      deque(const deque& __x) : _Base(__x.get_allocator(), __x.size()) 
        { uninitialized_copy(__x.begin(), __x.end(), _M_start); }
      deque(size_type __n, const value_type& __value,
            const allocator_type& __a = allocator_type()) : _Base(__a, __n)
        { _M_fill_initialize(__value); }
      explicit deque(size_type __n) : _Base(allocator_type(), __n)
        { _M_fill_initialize(value_type()); }
    
    #ifdef __STL_MEMBER_TEMPLATES
    
      // Check whether it's an integral type.  If so, it's not an iterator.
      template <class _InputIterator>
      deque(_InputIterator __first, _InputIterator __last,
            const allocator_type& __a = allocator_type()) : _Base(__a) {
        typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
        _M_initialize_dispatch(__first, __last, _Integral());
      }
    
      template <class _Integer>
      void _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) {
        _M_initialize_map(__n);
        _M_fill_initialize(__x);
      }
    
      template <class _InputIter>
      void _M_initialize_dispatch(_InputIter __first, _InputIter __last,
                                  __false_type) {
        _M_range_initialize(__first, __last, __ITERATOR_CATEGORY(__first));
      }
    
    #else /* __STL_MEMBER_TEMPLATES */
    
      deque(const value_type* __first, const value_type* __last,
            const allocator_type& __a = allocator_type()) 
        : _Base(__a, __last - __first)
        { uninitialized_copy(__first, __last, _M_start); }
      deque(const_iterator __first, const_iterator __last,
            const allocator_type& __a = allocator_type()) 
        : _Base(__a, __last - __first)
        { uninitialized_copy(__first, __last, _M_start); }
    
    #endif /* __STL_MEMBER_TEMPLATES */
    
     ~deque() { destroy(_M_start, _M_finish); }
    

    deque 的成员函数

    迭代器

      iterator begin() { return _M_start; }
      iterator end() { return _M_finish; }
      const_iterator begin() const { return _M_start; }
      const_iterator end() const { return _M_finish; }
    
      reverse_iterator rbegin() { return reverse_iterator(_M_finish); }
      reverse_iterator rend() { return reverse_iterator(_M_start); }
      const_reverse_iterator rbegin() const 
        { return const_reverse_iterator(_M_finish); }
      const_reverse_iterator rend() const 
        { return const_reverse_iterator(_M_start); }
    
      reference operator[](size_type __n)
        { return _M_start[difference_type(__n)]; }
      const_reference operator[](size_type __n) const 
        { return _M_start[difference_type(__n)]; }
    

    访问

      reference operator[](size_type __n)
        { return _M_start[difference_type(__n)]; }
      const_reference operator[](size_type __n) const 
        { return _M_start[difference_type(__n)]; }
        
    #ifdef __STL_THROW_RANGE_ERRORS
      void _M_range_check(size_type __n) const {
        if (__n >= this->size())
          __stl_throw_range_error("deque");
      }
      // at 实现
      reference at(size_type __n)
        { _M_range_check(__n); return (*this)[__n]; }
      const_reference at(size_type __n) const
        { _M_range_check(__n); return (*this)[__n]; }
    #endif /* __STL_THROW_RANGE_ERRORS */
      // front,back 实现
      reference front() { return *_M_start; }
      reference back() {
        iterator __tmp = _M_finish;
        --__tmp;
        return *__tmp;
      }
      const_reference front() const { return *_M_start; }
      const_reference back() const {
        const_iterator __tmp = _M_finish;
        --__tmp;
        return *__tmp;
      }
    

    容量

      size_type size() const { return _M_finish - _M_start; }
      size_type max_size() const { return size_type(-1); }
      bool empty() const { return _M_finish == _M_start; }
    

    修改器

     //@ 交换两个容器的内容
     //@这里实际上并没有交换具体的元素,而是交换迭代器和中控器信息
     void swap(deque& __x) {
        __STD::swap(_M_start, __x._M_start);
        __STD::swap(_M_finish, __x._M_finish);
        __STD::swap(_M_map, __x._M_map);
        __STD::swap(_M_map_size, __x._M_map_size);
      }
    
    public: 
      // assign(), a generalized assignment member function.  Two
      // versions: one that takes a count, and one that takes a range.
      // The range version is a member template, so we dispatch on whether
      // or not the type is an integer.
      
      void _M_fill_assign(size_type __n, const _Tp& __val) {
        if (__n > size()) {	//@ 若新的大小比容器原来的大
          fill(begin(), end(), __val);	//@把原来容器填充为val
          insert(end(), __n - size(), __val); //@ 容器追加填充值
        }
        else {	//@ 若新的大小比容器原来的小
          erase(begin() + __n, end());	//@ 则擦除多余的内容
          fill(begin(), end(), __val);  //@ 填充值为val覆盖原来的内容
        }
      }
      
      //@ 对外接口的assign第一个版本
      void assign(size_type __n, const _Tp& __val) {
        _M_fill_assign(__n, __val);
      }
    
    #ifdef __STL_MEMBER_TEMPLATES
       //@ 对外接口的assign第二个版本
      //@ 采用迭代器的traist技术
      template <class _InputIterator>
      void assign(_InputIterator __first, _InputIterator __last) {
        typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
        _M_assign_dispatch(__first, __last, _Integral());
      }
    
    private:   //@ assign() 辅助函数
    
      template <class _Integer>
      void _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
        { _M_fill_assign((size_type) __n, (_Tp) __val); }
    
      template <class _InputIterator>
      void _M_assign_dispatch(_InputIterator __first, _InputIterator __last,
                              __false_type) {
        _M_assign_aux(__first, __last, __ITERATOR_CATEGORY(__first));
      }
    
      template <class _InputIterator>
      void _M_assign_aux(_InputIterator __first, _InputIterator __last,
                         input_iterator_tag);
    
      template <class _ForwardIterator>
      void _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
                         forward_iterator_tag) {
        size_type __len = 0;
        distance(__first, __last, __len); //@ 计算两个输入迭代器的距离
        if (__len > size()) { //@ 若输入迭代器距离比待赋值容器大小还大
          _ForwardIterator __mid = __first;
          advance(__mid, size()); //@ 将mid向前移动size()个距离
          copy(__first, __mid, begin()); //@ 先复制[first,mid)数据
          insert(end(), __mid, __last); //@ 插入剩下的数据
        }
        else  //@ 否则擦除多余的数据
          erase(copy(__first, __last, begin()), end());
      }
    
    #endif /* __STL_MEMBER_TEMPLATES */
    
    public:                         // push_* and pop_*
      //@ 在容器尾部加数据
      void push_back(const value_type& __t) {
      //@ 若当前缓冲区存在可用空间
        if (_M_finish._M_cur != _M_finish._M_last - 1) {
          construct(_M_finish._M_cur, __t); //@ 直接构造对象
          ++_M_finish._M_cur; //@ 调整指针所指位置
        }
        else  //@ 若当前缓冲区不存在可用空间,需分配一段新的连续空间
          _M_push_back_aux(__t);
      }
    
      void push_back() {
        if (_M_finish._M_cur != _M_finish._M_last - 1) {
          construct(_M_finish._M_cur);
          ++_M_finish._M_cur;
        }
        else
          _M_push_back_aux();
      }
      // push_front
      void push_front(const value_type& __t) {
        if (_M_start._M_cur != _M_start._M_first) {
          construct(_M_start._M_cur - 1, __t);
          --_M_start._M_cur;
        }
        else
          _M_push_front_aux(__t);
      }
    
      void push_front() {
        if (_M_start._M_cur != _M_start._M_first) {
          construct(_M_start._M_cur - 1);
          --_M_start._M_cur;
        }
        else
          _M_push_front_aux();
      }
    
      // pop_back
      void pop_back() {
        if (_M_finish._M_cur != _M_finish._M_first) {
          --_M_finish._M_cur;
          destroy(_M_finish._M_cur);
        }
        else
          _M_pop_back_aux();
      }
      
      // pop_front
      void pop_front() {
        if (_M_start._M_cur != _M_start._M_last - 1) {
          destroy(_M_start._M_cur);
          ++_M_start._M_cur;
        }
        else 
          _M_pop_front_aux();
      }
    
    public:                         // Insert
      // insert(pos, x)
      iterator insert(iterator position, const value_type& __x) {
        if (position._M_cur == _M_start._M_cur) { //@ 若当前位置为deque.begin()
          push_front(__x); //@ 则在容器头部插入数据
          return _M_start;
        }
        else if (position._M_cur == _M_finish._M_cur) {
          push_back(__x);
          iterator __tmp = _M_finish;
          --__tmp;
          return __tmp;
        }
        else { //@ 否则在容器直接插入数据
          return _M_insert_aux(position, __x);
        }
      }
    
      iterator insert(iterator __position)
        { return insert(__position, value_type()); }
    
      void insert(iterator __pos, size_type __n, const value_type& __x)
        { _M_fill_insert(__pos, __n, __x); }
    
      void _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); 
    
    #ifdef __STL_MEMBER_TEMPLATES  
    
      // Check whether it's an integral type.  If so, it's not an iterator.
      template <class _InputIterator>
      void insert(iterator __pos, _InputIterator __first, _InputIterator __last) {
        typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
        _M_insert_dispatch(__pos, __first, __last, _Integral());
      }
    
      template <class _Integer>
      void _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x,
                              __true_type) {
        _M_fill_insert(__pos, (size_type) __n, (value_type) __x);
      }
    
      template <class _InputIterator>
      void _M_insert_dispatch(iterator __pos,
                              _InputIterator __first, _InputIterator __last,
                              __false_type) {
        insert(__pos, __first, __last, __ITERATOR_CATEGORY(__first));
      }
    
    #else /* __STL_MEMBER_TEMPLATES */
    
      void insert(iterator __pos,
                  const value_type* __first, const value_type* __last);
      void insert(iterator __pos,
                  const_iterator __first, const_iterator __last);
    
    #endif /* __STL_MEMBER_TEMPLATES */
      //@ 改变容器大小
      void resize(size_type __new_size, const value_type& __x) {
        const size_type __len = size();
        if (__new_size < __len)  //@ 新的大小较旧的小 
          erase(_M_start + __new_size, _M_finish); //@ 擦除多余的元素
        else //@ 否则,填充新增的节点
          insert(_M_finish, __new_size - __len, __x);
      }
    
      void resize(size_type new_size) { resize(new_size, value_type()); }
    
    public:                 
        //@ 擦除指定位置的元素:iterator erase (iterator position);
        //@ 擦除指定区间的元素:iterator erase (iterator first, iterator last);
    		
      iterator erase(iterator __pos) {
        iterator __next = __pos;
        ++__next;
        difference_type __index = __pos - _M_start; //@ 擦除点之前元素个数
        if (size_type(__index) < (this->size() >> 1)) { //@ 若擦除点之前的元素个数较少
          copy_backward(_M_start, __pos, __next); //@ 向后移动擦除点之前的元素
          pop_front();
        }
        else {
          copy(__next, _M_finish, __pos); //@ 否则,向前移动擦除点之后的元素
          pop_back();
        }
        return _M_start + __index;
      }
    
      iterator erase(iterator __first, iterator __last);
      void clear(); 
    
    protected:                        // Internal construction/destruction
    
      void _M_fill_initialize(const value_type& __value);
    
    #ifdef __STL_MEMBER_TEMPLATES  
    
      template <class _InputIterator>
      void _M_range_initialize(_InputIterator __first, _InputIterator __last,
                            input_iterator_tag);
    
      template <class _ForwardIterator>
      void _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
                            forward_iterator_tag);
    
    #endif /* __STL_MEMBER_TEMPLATES */
    
    protected:                        // Internal push_* and pop_*
    
      void _M_push_back_aux(const value_type&);
      void _M_push_back_aux();
      void _M_push_front_aux(const value_type&);
      void _M_push_front_aux();
      void _M_pop_back_aux();
      void _M_pop_front_aux();
    
    protected:                        // Internal insert functions
    
    #ifdef __STL_MEMBER_TEMPLATES  
    
      template <class _InputIterator>
      void insert(iterator __pos, _InputIterator __first, _InputIterator __last,
                  input_iterator_tag);
    
      template <class _ForwardIterator>
      void insert(iterator __pos,
                  _ForwardIterator __first, _ForwardIterator __last,
                  forward_iterator_tag);
    
    #endif /* __STL_MEMBER_TEMPLATES */
    
      iterator _M_insert_aux(iterator __pos, const value_type& __x);
      iterator _M_insert_aux(iterator __pos);
      void _M_insert_aux(iterator __pos, size_type __n, const value_type& __x);
    
    #ifdef __STL_MEMBER_TEMPLATES  
    
      template <class _ForwardIterator>
      void _M_insert_aux(iterator __pos, 
                         _ForwardIterator __first, _ForwardIterator __last,
                         size_type __n);
    
    #else /* __STL_MEMBER_TEMPLATES */
      
      void _M_insert_aux(iterator __pos,
                         const value_type* __first, const value_type* __last,
                         size_type __n);
    
      void _M_insert_aux(iterator __pos, 
                         const_iterator __first, const_iterator __last,
                         size_type __n);
     
    #endif /* __STL_MEMBER_TEMPLATES */
    
      iterator _M_reserve_elements_at_front(size_type __n) {
        size_type __vacancies = _M_start._M_cur - _M_start._M_first;
        if (__n > __vacancies) 
          _M_new_elements_at_front(__n - __vacancies);
        return _M_start - difference_type(__n);
      }
    
      iterator _M_reserve_elements_at_back(size_type __n) {
        size_type __vacancies = (_M_finish._M_last - _M_finish._M_cur) - 1;
        if (__n > __vacancies)
          _M_new_elements_at_back(__n - __vacancies);
        return _M_finish + difference_type(__n);
      }
    
      void _M_new_elements_at_front(size_type __new_elements);
      void _M_new_elements_at_back(size_type __new_elements);
    
    protected:                      // Allocation of _M_map and nodes
    
      // Makes sure the _M_map has space for new nodes.  Does not actually
      //  add the nodes.  Can invalidate _M_map pointers.  (And consequently, 
      //  deque iterators.)
    
      void _M_reserve_map_at_back (size_type __nodes_to_add = 1) {
      //@ _M_map_size - (_M_finish._M_node - _M_map)表示map尾端节点的备用空间
        if (__nodes_to_add + 1 > _M_map_size - (_M_finish._M_node - _M_map))
          _M_reallocate_map(__nodes_to_add, false);
      }
    
      void _M_reserve_map_at_front (size_type __nodes_to_add = 1) {
      //@ _M_start._M_node - _M_map表示map头部节点的备用空间
        if (__nodes_to_add > size_type(_M_start._M_node - _M_map))
          _M_reallocate_map(__nodes_to_add, true);
      }
    
      void _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front);
    
    

    总结

    • deque 是一种双向开口的分段连续线性空间,可以在头尾两端进行push和pop,可以在内部进行插入和删除。
    • 迭代器不能使用普通指针,属于随机访问迭代器。因而 deque 支持随机访问。
    • 首尾插入与删除的时间复杂度为 O(1),随机访问时间复杂度为 O(1),内部插入与删除的时间复杂度为 O(n)。
  • 相关阅读:
    笨方法学python中执行argv提示ValueError: not enough values to unpack (expected 4, got 1)
    VMware workstation安装
    Redis bigkey分析
    MySQL drop table 影响及过程
    MySQL 大表硬连接删除
    ES elasticsearch 各种查询
    ES elasticsearch 各种聚合
    ES elasticsearch 聚合统计
    ES elasticsearch 实现 count单字段,分组取前多少位,以地理位置中心进行统计
    MySQL行溢出、varchar最多能存多少字符
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12602870.html
Copyright © 2011-2022 走看看