zoukankan      html  css  js  c++  java
  • STL源码阅读(三)

    STL源码阅读(三) (SGI STL v3.3)

    stl_list.h (<list>)

    // list结点基类
    struct _List_node_base {
      _List_node_base* _M_next; // 指向下一个结点
      _List_node_base* _M_prev; // 指向前一个结点
    };
    
    // list结点
    template <class _Tp>
    struct _List_node : public _List_node_base {
      _Tp _M_data;  // 每个结点上的数据
    };
    
    // list迭代器,迭代器类型双向迭代器
    struct _List_iterator_base;
    template<class _Tp, class _Ref, class _Ptr>
    struct _List_iterator : public _List_iterator_base;
    
    // _M_node指向list结点,每次迭代更新迭代器的_M_node的指向
    _List_node_base* _M_node;   // 指向list结点
    
    // list内存分配
    // 该类中保存了内存分配器_Node_allocator与所分配的_List_node结点内存的指针_M_node
    template <class _Tp, class _Allocator, bool _IsStatic>
    class _List_alloc_base;
    // _List_alloc_base的特化版本,不需保存内存分配器(使用静态的分配器),只有一个数据成员_M_node
    template <class _Tp, class _Allocator>
    class _List_alloc_base<_Tp, _Allocator, true>;
    
    // list基类
    template <class _Tp, class _Alloc>
    class _List_base 
      : public _List_alloc_base<_Tp, _Alloc,
                                _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
    {
    public:
      typedef _List_alloc_base<_Tp, _Alloc,
                               _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
              _Base; 
      typedef typename _Base::allocator_type allocator_type;
    
      _List_base(const allocator_type& __a) : _Base(__a) {
        _M_node = _M_get_node();        // 获得一个新结点
        _M_node->_M_next = _M_node;     // list是一个双向环向状量表,哨兵结点
        _M_node->_M_prev = _M_node;
      }
      ~_List_base() {
        clear();    // 清除链表中的所有元素
        _M_put_node(_M_node);  // 由此可见list有一个哨兵结点,不存数据,指向整个链表
      }
    
      void clear();
    };
    
    // 清除量表中的所有元素   
    template <class _Tp, class _Alloc>
    void _List_base<_Tp,_Alloc>::clear() 
    {
      _List_node<_Tp>* __cur = (_List_node<_Tp>*) _M_node->_M_next;
      while (__cur != _M_node) {
        _List_node<_Tp>* __tmp = __cur;
        __cur = (_List_node<_Tp>*) __cur->_M_next;
        _Destroy(&__tmp->_M_data);
        _M_put_node(__tmp);
      }
      _M_node->_M_next = _M_node;
      _M_node->_M_prev = _M_node;
    }
    
    template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
    class list : protected _List_base<_Tp, _Alloc>;
    
    // list中_M_node是指向哨兵结点的
    iterator begin()             { return (_Node*)(_M_node->_M_next); }
    
    // 注意swap只是交换哨兵结点的指针
    void swap(list<_Tp, _Alloc>& __x) { __STD::swap(_M_node, __x._M_node); }
    
    // 将[__first, __last)中的元素移到__position之前,splice的实现
    void transfer(iterator __position, iterator __first, iterator __last) {
        if (__position != __last) {
          // Remove [first, last) from its old position.
          __last._M_node->_M_prev->_M_next     = __position._M_node;
          __first._M_node->_M_prev->_M_next    = __last._M_node;
          __position._M_node->_M_prev->_M_next = __first._M_node; 
    
          // Splice [first, last) into its new position.
          _List_node_base* __tmp      = __position._M_node->_M_prev;
          __position._M_node->_M_prev = __last._M_node->_M_prev;
          __last._M_node->_M_prev     = __first._M_node->_M_prev; 
          __first._M_node->_M_prev    = __tmp;
        }
    }
    
    // 注意,unique是移除连续相等的元素
    template <class _Tp, class _Alloc>
    void list<_Tp, _Alloc>::unique()
    {
      iterator __first = begin();
      iterator __last = end();
      if (__first == __last) return;
      iterator __next = __first;
      while (++__next != __last) {
        if (*__first == *__next)
          erase(__next);
        else
          __first = __next;
        __next = __first;
      }
    }
    
    // merge两个已排序的list,按升序
    template <class _Tp, class _Alloc>
    void list<_Tp, _Alloc>::merge(list<_Tp, _Alloc>& __x)
    {
      iterator __first1 = begin();
      iterator __last1 = end();
      iterator __first2 = __x.begin();
      iterator __last2 = __x.end();
      while (__first1 != __last1 && __first2 != __last2)
        if (*__first2 < *__first1) {
          iterator __next = __first2;
          transfer(__first1, __first2, ++__next);
          __first2 = __next;
        }
        else
          ++__first1;
      if (__first2 != __last2) transfer(__last1, __first2, __last2);
    }
    
    
    // 没弄懂reverse的实现
    inline void __List_base_reverse(_List_node_base* __p)
    {
      _List_node_base* __tmp = __p;
      do {
        __STD::swap(__tmp->_M_next, __tmp->_M_prev);
        __tmp = __tmp->_M_prev;     // Old next node is now prev.
      } while (__tmp != __p);
    }
    
    template <class _Tp, class _Alloc>
    inline void list<_Tp, _Alloc>::reverse() 
    {
      __List_base_reverse(this->_M_node);
    }    
    
    // 归并算法实现list sort排序,保持相等元素的相对顺序
    template <class _Tp, class _Alloc>
    void list<_Tp, _Alloc>::sort()
    {
      // Do nothing if the list has length 0 or 1.
      if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) {
        list<_Tp, _Alloc> __carry;
        list<_Tp, _Alloc> __counter[64];    // 模拟递归实现
        int __fill = 0;
        while (!empty()) {
          __carry.splice(__carry.begin(), *this, begin());
          int __i = 0;
          while(__i < __fill && !__counter[__i].empty()) {
            __counter[__i].merge(__carry);
            __carry.swap(__counter[__i++]);
          }
          __carry.swap(__counter[__i]);         
          if (__i == __fill) ++__fill;
        } 
    
        for (int __i = 1; __i < __fill; ++__i)
          __counter[__i].merge(__counter[__i-1]);
        swap(__counter[__fill-1]);
      }
    }

    参考资料

    1. sgi STL
    2. cppreference.com
  • 相关阅读:
    而立之年的程序员创业者,写给不甘平凡的自己和80、90后!
    无焦虑,不成长!三大方法让你走出焦虑!
    [Chat]实战:仿网易云课堂微信小程序开发核心技术剖析和经验分享
    [干货教程]仿网易云课堂微信小程序开发实战经验
    微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法
    微信支付之扫码支付开发:我遇到的坑及解决办法(附:Ecshop 微信支付插件)
    OpenCV 4.3 编译和配置
    OpenCV 之 基本绘图
    OpenCV 之 空间滤波
    Qt 地址薄 (二) 添加地址
  • 原文地址:https://www.cnblogs.com/corfox/p/6063306.html
Copyright © 2011-2022 走看看