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

 

posted @ 2019-12-17 15:36  Vzf  阅读(250)  评论(0编辑  收藏  举报