STL-Deque的实现

1.STL-Deque的原理

元素的插入

buyback:

pointer _P = allocator.allocate(_DEQUESIZE, (void*)0);
        if (empty())
        {
            _Mapsize = _DEQUEMAPSIZE;
            size_type _N = _Mapsize / 2;
            _Getmap();
            _Setptr(_Map + _N, _P);
            _First = iterator(_P + _DEQUESIZE / 2, _Map + _N);
            _Last = _First;
        }

当deque为空时

当为empty时,双端队列的实现就是分配一个空间,重中间分开,前部分是_First,后半部分是_Last; _First从中间位置,后退插入;_Last从中间往后插入;这样就实现了front和back插入。

map空间不足的增长

1.超过前半部分(_first)的空间

创建map空间,并把原来的map空间拷贝新分配的空间;新分配的空间,仅仅给前半部分的使用。

_Mapptr _M = _Growmap(2 * _I);
            _Setptr(--M, P);
            _First = iterator(_P + _DEQUESIZE, _M);
            _Last = iterator(_Last._Next, _M + _I);

2.超过后半部分(_Last)的空间

创建map空间,并把原来的map空间拷贝新分配的空间。新分配的空间,不再从中间划分,仅仅给后半部使用;

int _I = _Last._Map - _First._Map + 1;
            _Mapptr _M = _Growmap(2 * _I);//增加映射器
            _Setptr(_M + 1,_P);

//维护原来的空间
            _First = iterator(_First._Next, _M);
            _Last = iterator(_P, _M + _I);

元素的删除操作

1.前向删除pop_front

删除前向元素,包括两个方面,当整个_First的_Map指向的空间没有了,一个是_First的指针的域的更新(_First,_Last,_Next,_Map),前向是插入式倒退进行,那删除就是前进方式,_Next肯定执行新空间的头部。

allocater.destroy(_First._Next++);

_First = iterator(*_First._Map, _First._Map);

另外一个方面就是空间的回收工作,一个空间管理者map空间,一个数据空间;首先会destory掉这个元素值得空间,然后会判断当前的一段空间是否到达末尾,如果到达就会先删除

掉这个_First指向的map空间;

_Freeptr(_First._Map++);//删除指向的_Map空间

如果这个时候,整个deque为空了,就要删除整个_Map.

_Freemap();

2.后向删除pop_back

删除后向元素,当整个_Last指向的_Map的空间没有了,也包括两个方面,一个是_Last的指针域的更新的,由于后向是前进插入的,那删除就是后退方式,_Next肯定指向新空间的尾部。

_Last = iterator(*_Last._Map + _DEQUESIZE, _Last._Map);

另一方面是是空间回收工作,一个_map空间,一个是数据空间;

_Freeptr(_Last.Map--);

allocator.destroy(--_Last._Next);

如果刚好整个deque的空间为空了:

_Freemap();

数据的访问

通过迭代器

iterator operator ++() {
            if (++_Next == _Last) {
                _First = *++_Map;
                _Last = _First + _DEQUESIZE;
                _Next = _First;
            }
            return *this;
        }

数据的插入

  • 情况1.当插入的iterator为begin时,就是push_front

if (_X == begin()) {
            push_front(_V);
        }

  • 情况2.当插入的iterator为end()时,就是push_back

 else if (_X == end()) {
            push_back(_V);
        }

  • 情况3:由于插入需要移动元素,如果距离头部的距离小于1/2的总大小,就移动头部的元素,否则移动后面的元素;

 else {

            difference_type _off = _X - begin();
            Myiterator _S;
            if (_off < size() / 2) {
                push_front(front());
                _S = begin() + _off;
                这个是把元素拷贝,begin()+2的原因是,头部的一个元素往前拷贝了一下,因此头部的两个元素都是第一个元素值。从第二个开始拷贝,开始的位置从begin()+1,覆盖掉一个相同的元素。
                std::copy<deque::Myiterator,deque::Myiterator>((begin() + 2),_S,(begin() + 1));
            }
            else {
                push_back(back());
                _S = begin() + _off;

这个是拷贝元素从从后往前拷贝,原理相同
                std::copy_backward(_S,(end() - 2),(end() - 1));
            }
            *_S = _V;
        }
        
    }

源码:

deque.h

#pragma once
#include"xmemory.h"

#define _DEQUEMAPSIZE 2
#define _DEQUESIZE ((4096<sizeof(_Ty))?1:4096/sizeof(_Ty))
template<class _Ty, class _A=Allocator<_Ty> >
class deque {
public:
    using size_type = typename _A::size_type;
    using difference_type = typename _A::difference_type;
    using reference = typename _A::reference;
    using pointer = typename _A::pointer_type;

    typedef _Ty** _Mapptr;

    class Myiterator{
    public:
        using size_type = typename _A::size_type;
        using difference_type = typename _A::difference_type;
        using reference = typename _A::reference;
        using pointer = typename _A::pointer_type;
        typedef const _Ty& const_reference;
        typedef _Ty value_type;
        using iterator_category = typename std::bidirectional_iterator_tag;
        friend class deque;
    public:
        explicit Myiterator() :_First(0), _Last(0), _Next(0), _Map(0) {

        }
        //,_Last(*_M+_DEQUESIZE),_Next(_P),_map(_M)
        Myiterator(pointer _P, _Mapptr _M):_First(*_M), _Last((*_M + _DEQUESIZE)), _Next(_P), _Map(_M) {

        }
        bool operator ==(const Myiterator& _X) {
            return _Next == _X._Next;
        }
        bool operator !=(const Myiterator& _X) {
            return !(*this == _X);
        }
        reference operator*() {
            return *_Next;
        }
        pointer operator->() {
            return **this;
        }
        Myiterator operator ++() {
            if (++_Next == _Last) {
                _First = *++_Map;
                _Last = _First + _DEQUESIZE;
                _Next = _First;
            }
            return *this;
        }
        Myiterator operator++(int) {
            Myiterator temp = *this;
            ++*this;
            return temp;
        }
        Myiterator operator--() {
            if (_Next == _First) {
                _First = *--_Map;
                _Last = _First + _DEQUEMAPSIZE;
                _Next = _Last;
            }
            --_Next;
            return *this;
        }
        Myiterator operator --(int) {
            Myiterator temp = *this;
            --*this;
            return temp;
        }
        void _Add(difference_type _N) {
            difference_type _off = _N + (_Next - _First);
            difference_type _Moff = (_off >= 0) ? _off / _DEQUESIZE : (-1)*((_DEQUESIZE - 1 - _off) / _DEQUESIZE);
            if (_Moff == 0) {
                _Next += _N;
            }
            else {
                _Map += _Moff;
                _First = *_Map;
                _Last = _First + _DEQUESIZE;
                _Next = _First + (_off - _Moff + _DEQUESIZE);
            }
        }
        Myiterator operator+=(difference_type _N) {
            _Add(_N);
            return *this;
        }
        Myiterator operator-=(difference_type _N) {
            _Add(-_N);
            return *this;
        }
        Myiterator operator+(difference_type _N) {
            Myiterator temp = *this;
            return temp+=_N;
        }
        Myiterator operator-(difference_type _N) {
            Myiterator temp = *this;
            return temp-=_N;
        }
        difference_type operator-(const Myiterator& _X) {
            return (_Map == _X._Map ? (_Next - _X._Next) : _DEQUESIZE * (_Map - _X._Map - 1) + (_Next - _First) + (_X._Last - _X._Next));
        }
        
    protected:
        pointer _First, _Last, _Next;
        _Mapptr _Map;
    };
public:
    explicit deque(const _A& A1 = _A()) :allocator(A1), _First(), _Last(), _Map(0), _Size(0) {

    }
    
    void insert(Myiterator& _X, const _Ty& _V) {
        if (_X == begin()) {
            push_front(_V);
        }
        else if (_X == end()) {
            push_back(_V);
        }
        else {
            difference_type _off = _X - begin();
            Myiterator _S;
            if (_off < size() / 2) {
                push_front(front());
                _S = begin() + _off;
                
                std::copy<deque::Myiterator,deque::Myiterator>((begin() + 2),_S,(begin() + 1));
            }
            else {
                push_back(back());
                _S = begin() + _off;
                std::copy_backward(_S,(end() - 2),(end() - 1));
            }
            *_S = _V;
        }
        
    }
    void push_back(const _Ty& _X) {
        if (empty() || _Last._Next == _Last._Last) {
            _Buyback();
            allocator.construct(_Last._Next++, _X);
        }
        else if (_Last._Next + 1 == _Last._Last) {
            allocator.construct(_Last._Next++, _X);
            _Buyback();
        }
        else {
            allocator.construct(_Last._Next++, _X);
        }
        ++_Size;
    }
    void push_front(const _Ty& _X) {
        if (empty() || _First._Next == _First._First) {
            _Buyfront();
        }
        allocator.construct(--_First._Next, _X);

    }
    size_type size() {
        return _Size;
    }
    bool empty() {
        return size() == 0;
    }
protected:
    void _Getmap() {
        _Map = (_Mapptr)allocator._Charallocate(_Mapsize * sizeof(pointer));
    }
    _Mapptr _Growmap(size_type _Newsize) {
        _Mapptr _M = (_Mapptr)allocator._Charallocate(_Newsize * sizeof(pointer));
        std::copy(_First._Map, _Last._Map + 1, _M + _Newsize / 4);
        allocator.deallocate(_Map, _Mapsize);
        _Map = _M;
        _Mapsize = _Newsize;
        return (_M + _Newsize / 4);
    }
    void _Setptr(_Mapptr _M, pointer _P) {
        *_M = _P;
    }
    void _Buyback() {
        pointer _P = allocator.allocate(_DEQUESIZE);
        if (empty())
        {
            _Mapsize = _DEQUEMAPSIZE;
            size_type _N = _Mapsize / 2;
            _Getmap();
            _Setptr(_Map + _N, _P);
            _First =Myiterator((pointer)(_P + _DEQUESIZE / 2), _Map + _N);
            _Last = _First;
        }
        else if (_Last._Map < _Map + (_Mapsize - 1)) {
            _Setptr(++_Last._Map, _P);
            _Last = Myiterator(_P, _Last._Map);
        }
        else {
                int _I = _Last._Map - _First._Map + 1;
                _Mapptr _M = _Growmap(2 * _I);
                _Setptr((_M + _I),_P);
                _First = Myiterator(_First._Next, _M);
                _Last = Myiterator(_P, _M + _I);
        }
    }
    void _Buyfront() {
        pointer _P = allocator.allocate(_DEQUESIZE);
        if (empty()) {
            _Mapsize = _DEQUEMAPSIZE;
            size_type _N = _Mapsize / 2;
            _Getmap();
            _Setptr(_Map + _N, _P);
            _First = Myiterator(_P + (_DEQUESIZE / 2 + 1), _Map + _N);
            _Last = _First;
        }
        else if (_Map < _First._Map) {
            _Setptr(--_First._Map, _P);
            _First = Myiterator(_P + _DEQUESIZE, _First._Map);
        }
        else if(_First._Map==_Last._Map){
            _Setptr(_Last._Map++, *_Last._Map);
            _Setptr(_First._Map + 1, *_First._Map);
            _Setptr(_First._Map, _P);
            _First = Myiterator(_P + _DEQUESIZE, _First._Map);
        }
        else {
            int _I = _Last._Map - _First._Map + 1;
            _Mapptr _M = _Growmap(2 * _I);
            _Setptr(--_M, _P);
            _First = Myiterator(_P + _DEQUESIZE, _M);
            _Last = Myiterator(_Last._Next, _M + _I);
        }
    }
    void _Freeptr(_Mapptr _M) {
        allocator.deallocate(*_M, _DEQUESIZE);
    }
    void _Freemap() {
        allocator.deallocate(_Map, _Mapsize);
    }
    void _Freefront() {
        _Freeptr(_First._Map++);
        if (empty()) {
            _First = Myiterator();
            _Last = _First;
            _Freemap();
        }
        else
            _First = Myiterator(*_First._Map, _First._Map);
    }
    void pop_front() {
        allocator.destroy(_First._Next++);
        --size;
        if (empty() || _First._Next == _First._Last) {
            _Freefront();
        }
    }
    void _Freeback() {
        _Freeptr(_Last.Map--);
        if (empty()) {
            if (_First._Map == _Last._Map) {
                _Freeptr(_First._Map);
            }
            _First = Myiterator();
            _Last = _First;
            _Freemap();
        }
        else {
            _Last = Myiterator(*_Last._Map + _DEQUESIZE, _Last._Map);
        }
    }
    void pop_back() {
        if (_Last._Next == _Last._First) {
            _Freeback();
        }
        if (!empty()) {
            allocator.destroy(--_Last._Next);
        }
        --size;
        if (empty()) {
            _Freeback();
        }
    }
public:
    Myiterator begin() {
        return _First;
    }
    Myiterator end() {
        return _Last;
    }
    reference front() {
        return *_First;
    }
    reference back() {
        return *_Last;
    }
private:
    _A allocator;
    Myiterator _First, _Last;
    _Mapptr _Map;
    size_type _Mapsize, _Size;

};

xmemory.h:

#pragma once
template <class _Ty>
_Ty* _allocate(size_t _N, _Ty*) {
    if (_N < 0)
        _N = 0;
    return (_Ty*)operator new(_N * sizeof(_Ty));
}
template <class _T1, class _T2>
void _Construct(_T1* p, const _T2& _v) {
    new ((void*)p) _T1(_v);
}
template<class _Ty>
void _Destroy(_Ty* _P) {
    _P->~_Ty();
}
template <class _Ty>
class Allocator {
public:
    typedef size_t size_type;
    typedef int difference_type;
    typedef _Ty* pointer_type;
    typedef _Ty& reference;
    typedef const _Ty& const_reference;
    pointer_type allocate(size_type n) {
        return _allocate(n, pointer_type(0));
    }
    char* _Charallocate(size_type n) {
        return _allocate(n, (char*)0);
    }
    void deallocate(void* p, size_type n) {
        operator delete(p);
    }
    void construct(pointer_type _P, const_reference _V) {
        _Construct(_P, _V);
    }
    void destroy(pointer_type _P) {
        _Destroy(_P);
    }
    size_t max_size() const
    {
        size_t _N = (size_t)(-1) / sizeof(_Ty);
        return _N;
    }
};


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值