zoukankan      html  css  js  c++  java
  • STL实现03---deque

    #ifndef M_DEQUE_H
    #define M_DEQUE_H
    /***************************************
     * Description:deque实现,使用场景,类似排队系统,队首和队尾不要频繁的删除和天剑
     * Create:2019/12/7
     * Author:zhangfeng
     * History:
     *      2019-12-7 搭建初步框架和基本接口
     *                
     *      
     * *************************************/
    #include <memory>
    #include <iostream>
    #include <algorithm>
    #include <cstddef>
    
    // Note: this function is simply a kludge to work around several compilers'
    //  bugs in handling constant expressions.
    inline size_t deque_buf_size(size_t __size) {
      return __size < 512 ? size_t(512 / __size) : size_t(1);
    }
    
    //迭代器
    template <class T, class Ref, class Ptr>
    struct Deque_iterator {
        typedef Deque_iterator<T, T&, T*>    iterator;
        typedef Deque_iterator<T, const T&, const T*> const_iterator;
        static size_t _S_buffer_size() { return deque_buf_size(sizeof(T)); }
    
        typedef Deque_iterator _Self;
    
        typedef T value_type;
        typedef Ptr pointer;
        typedef Ref reference;
        typedef size_t size_type;
        typedef ptrdiff_t difference_type;
        typedef T** _Map_pointer;
    
        T* _cur;   //缓冲区的现行
        T* _first; //缓冲区的头
        T* _last;  //缓冲区的尾
        _Map_pointer _node; //指向管控中心
    
        Deque_iterator() : _cur(0), _first(0), _last(0), _node(0) {}
    
        reference operator*() const { return *_cur; }
        reference operator->() const { return *_cur; }
    
        difference_type operator-(const _Self& _x) const {
            return  difference_type(_S_buffer_size()) * (_node - _x._node -1) + (_cur - _first) + (_last - _cur);
        }
    
        _Self& operator++() {
            ++_cur;
            if(_cur == _last) {
                set_node(_node + 1);
                _cur = _first;
            }
            return *this;
        } 
    
        _Self operator++(int) {
            _Self _tmp = *this;
            ++*this;
            return _tmp;
        }
    
        _Self& operator--() {
            if(_cur == _first) {
                set_node(_node - 1);
                _cur = _last;
            }
            --_cur;
            return *this;
        }
    
        _Self operator--(int) {
            _Self _tmp = *this;
            --*this;
            return _tmp;
        }
    
        _Self& operator+=(difference_type _n) {
            difference_type _offset = _n + (_cur - _first);
            if(_offset >= 0 && _offset <  difference_type(_S_buffer_size())) {
                _cur += _n;
            } else {
                difference_type _node_offset = 
                    _offset > 0 ? _offset / difference_type(_S_buffer_size())
                       : -difference_type((-_offset - 1) / _S_buffer_size()) - 1;
                set_node(_node + _node_offset);
                _cur = _first + (_offset - _node_offset * difference_type(_S_buffer_size()));
            }
            return *this;
        }
    
        _Self operator+(difference_type _n) const {
            _Self _tmp = *this;
            return _tmp += _n;
        }
    
        _Self& operator-=(difference_type _n) {
            return *this += -_n;
        }
    
        reference operator[](difference_type _n) {
            return *(*this + _n);
        }
    
        bool operator==(const _Self& _x) const { return this->_cur == _x._cur; }
        bool operator!=(const _Self& _x) const { return !(*this == _x); }
    
        void set_node(_Map_pointer _new_node) {
            _node = _new_node;
            _first = *_new_node;
            _last = _first + difference_type(_S_buffer_size());
        }
    };
    
    template <class T>
    class mDeque_base {
    public:
        typedef Deque_iterator<T, T&, T*>             iterator;
        typedef Deque_iterator<T, const T&, const T*> const_iterator;
        typedef T** _Map_pointer;
    
        mDeque_base() : _map(0), _map_size(0), _start(), _finish() {}
        mDeque_base(size_t _num)
            : _map(0), _map_size(0), _start(), _finish() {
                init_map(_num);
        }
        ~mDeque_base() {
            if(_map) {
                destroy_node(_start._node, _finish._node + 2);
                deallocate_map(_map, _map_size);
            }
        }
    protected:
        void init_map(size_t);
        void create_node(_Map_pointer _nstart, _Map_pointer _nfinish);
        void destroy_node(_Map_pointer _nstart, _Map_pointer _nfinish);
    
        T* allocate_node() { return _Node_alloc.allocate(deque_buf_size(sizeof(T))); }
        void deallocate_node(T* _p) { _Node_alloc.deallocate(_p, deque_buf_size(sizeof(T)));}
        T** allocate_map(size_t _n) { return _Map_alloc.allocate(_n); }
        void deallocate_map(T** _p, size_t _n) { return _Map_alloc.deallocate(_p, _n); }
    
        
        enum { _S_initial_map_size = 8 };
    protected:
        T** _map;
        size_t _map_size;
        iterator _start;
        iterator _finish;
    
        std::allocator<T> _Node_alloc;
        std::allocator<T*> _Map_alloc;
    };
    
    template <class T>
    void mDeque_base<T>::init_map(size_t _num_elements)
    {
        size_t _num_node = _num_elements / deque_buf_size(sizeof(T)) + 1;
    
        _map_size = std::max((size_t)_S_initial_map_size, _num_node + 2);
        _map = _Map_alloc.allocate(_map_size);
        
        _Map_pointer _nstart = _map + (_map_size - _num_node) / 2;
        _Map_pointer _nfinish = _nstart + _num_node;
    
        try {
            create_node(_nstart, _nfinish);
        }
        catch(...) {
            _Map_alloc.deallocate(_map, _map_size);
            _map = 0;
            _map_size = 0;
        }
        _start.set_node(_nstart);
        _finish.set_node(_nfinish);
        _start._cur = _start._first;
        _finish._cur = _start._first + _num_elements % deque_buf_size(sizeof(T));
    
    }
    
    template <class T>
    void mDeque_base<T>::create_node(_Map_pointer _nstart, _Map_pointer _nfinish)
    {
        _Map_pointer _cur;
        try {
            for(_cur=_nstart; _cur != _nfinish; ++_cur) {
                *_cur = allocate_node();
            }
        }
        catch(...) {
            destroy_node(_nstart, _nfinish);
        }
    }
    
    template <class T>
    void mDeque_base<T>::destroy_node(_Map_pointer _nstart, _Map_pointer _nfinish)
    {
        for(_Map_pointer _cur=_nstart; _cur != _nfinish; ++_cur) {
            deallocate_node(*_cur);
        }
    }
    
    template <class T>
    class mDeque : protected mDeque_base<T> {
    public:
        typedef T value_type; 
        typedef value_type* pointer;
        typedef const value_type* const_pointer;
        typedef value_type& reference;
        typedef const value_type& const_reference;
        typedef size_t size_type;
        typedef ptrdiff_t difference_type;
        typedef T** _Map_pointer;
        typedef mDeque_base<T> _Base;
    public:
        typedef typename _Base::iterator iterator;
        typedef typename _Base::const_iterator const_iterator;
    
    protected:
        using _Base::_map;
        using _Base::_map_size;
        using _Base::_start;
        using _Base::_finish;
        using _Base::_Node_alloc;
        using _Base::_Map_alloc;
    
        using _Base::allocate_node;
        using _Base::deallocate_node;
    public:
        mDeque() : _Base(0) {}
        ~mDeque() { destroy(_start, _finish); }
    
        void push_back(const value_type& _t);
    
    //元素访问
        reference operator[](size_t _n) {
            return _start[difference_type(_n)];
        }
    
    protected:
        void push_back_aux(const value_type&);
        void reserve_map_at_back(size_type _nodes_to_add = 1) {
            if(_nodes_to_add + 1 > _map_size - (_finish._node - _map)) {
                reallocate_map(_nodes_to_add, false);
            }
        }
        void reallocate_map(size_type _nodes_to_add, bool __add_at_front);
        void destroy(iterator start, iterator finist) {
            for(; start != finist; start++){
                _Map_alloc.destroy(&(*start));
            }
        }
    };
    
    template <class T>
    void mDeque<T>::push_back(const value_type& _t) 
    {
        if(_finish._cur != _finish._last - 1) {
            _Node_alloc.construct(_finish._cur, _t); 
            ++_finish._cur;
        } else {
            push_back_aux(_t);
        }
    }
    
    template <class T>
    void mDeque<T>::push_back_aux(const value_type& _t)
    {
        value_type _t_copy = _t;
        reserve_map_at_back();
        *(_finish._node + 1) = allocate_node();
        try {
            _Node_alloc.construct(_finish._cur, _t_copy); 
            _finish.set_node(_finish._node + 1);
            _finish._cur = _finish._first;
        }
        catch(...) {
            deallocate_node(*(_finish._node + 1));
        }
    }
    
    template <class T>
    void mDeque<T>::reallocate_map(size_type _nodes_to_add, bool _add_at_front)
    {
        size_type _old_num_nodes = _finish._node - _start._node + 1;
        size_type _new_num_nodes = _old_num_nodes + _nodes_to_add;
    
        _Map_pointer _new_nstart;
        if (_map_size > 2 * _new_num_nodes) {
            _new_nstart = _map + (_map_size - _new_num_nodes)/2 
                            + (_add_at_front ?  _nodes_to_add : 0);
            
            if(_new_nstart < _start._node) {
                std::copy(_start._node, _finish._node + 1, _new_nstart);
            } else {
                std::copy_backward(_start._node, _finish._node + 1, _new_nstart + _old_num_nodes);
            }
        } else {
            size_type _new_map_size = _map_size + std::max(_map_size, _nodes_to_add) + 2;
    
            _Map_pointer _new_map = _Map_alloc.allocate(_new_map_size);
            _new_nstart = _new_map + (_new_map_size - _new_num_nodes)/2 
                            + (_add_at_front ?  _nodes_to_add : 0);
            std::copy(_start._node, _finish._node + 1, _new_nstart);
            _Map_alloc.deallocate(_map, _map_size);
    
            _map = _new_map;
            _map_size = _new_map_size;
        }
    
        _start.set_node(_new_nstart);
        _finish.set_node(_new_nstart + _old_num_nodes - 1);
    }
    
    #endif
  • 相关阅读:
    Swift
    Swift
    POJ2029——Get Many Persimmon Trees
    windows-install-python-and-sphinx(*.rst file)
    【cocos2d-x】尝鲜 Cocos Code IDE(不断更新)
    mysql 删除重复数据sql声明
    开销是有益的:AppCan 至HTML5移动创新和创业精神和健康
    hibernate它5.many2one单向
    Insecure default in Elasticsearch enables remote code execution
    TestNg显示器(一个)-----监听器,类型和配置使用---另外META-INF详细解释
  • 原文地址:https://www.cnblogs.com/vczf/p/12054843.html
Copyright © 2011-2022 走看看