您的位置:首页 > 产品设计 > UI/UE

STL_deque

2016-03-03 18:40 627 查看
#include<new>
#include<stdlib.h>
#include<cstddef>
const size_t BufSiz = 512;
size_t max(size_t a, size_t b)
{
if (a > b)
return a;
else
return b;
}
template<class B1, class B2>
B2 copy_backword(B1 first, B1 last, B2 result)
{
while (last != first)
*(--result) = *(--last);
return result;
}
template <class I, class O>
inline void copy(I first, I last, O result)
{
for (; first != last; ++result, ++first)
*result = *first;
return result;
}
template <class T1, class T2>
inline void construct(T1* p, const T2& value)
{
new (p)T1(value);
}

template <class T>
inline void destroy(T * pointer)
{
pointer->~T();//ÏÔʽµÄµ÷ÓÃTµÄÎö¹¹
}
template <class T>
inline void destroy(T * first, T * last)
{
for (; first < last; ++first)
{
destroy(&*first);
}
}
template <class F, class T>
void uninitialized_fill(F first, F last, const T& x)
{
F cur = first;
for (; cur != last; ++cur)
{
construct(&*cur, x);
}
}
template <class T>
class simple_alloc
{
private:
static void * allocate_malloc(size_t n)
{
void * result = malloc(n);
return result;
}
static void deallocate(void * p, size_t)
{
//
free(p);
}
public:
static T * allocate(size_t n)
{
if (n == 0)
return 0;
else
{
return (T*)allocate_malloc(n * sizeof(T));
}
}
static T * allocate(void)
{
return (T*)allocate_malloc(sizeof(T));
}
static void deallocate(T *p, size_t n)
{
if (0 != n)
{
dellocate_free(p, n*sizeof(T));
}

}
static void deallocate(T *p)
{
dellocate_free(p, sizeof(T));
}
};

inline size_t deque_buf_size(size_t n, size_t sz)//·µ»Ø»º³åÇø´óС
{
return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
}

template <class T , class Ref , class Ptr , size_t = BufSiz>
class deque_iterator
{
public:
typedef deque_iterator<T, T&, T*, BufSiz>               iterator;
typedef deque_iterator<T, const T&, const T* , BufSiz> const_iterator;

static size_t buffer_size()
{
return deque_buf_size(BufSiz, sizeof(T));
}

typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T** map_pointer;

typedef deque_iterator self;

T* cur_;//Ö¸Ïò»º³åÇøÏÖÔÚµÄÔªËØ
T* first_;//Ö¸Ïò»º³åÇøÍ·
T* last_;//Ö¸Ïò»º³åÇøβ
map_pointer node_;

void set_node(map_pointer new_node)
{
node_ = new_node;
first_ = *new_node;
last_ = first_ + difference_type(buffer_size());
}

reference operator*() const
{
return *cur_;
}
pointer operator->() const
{
return &(operator*());
}
difference_type operator-(const self& x) const
{
return difference_type(buffer_size())*(node_ - x.node_ - 1) + (cur_ - first_) + (x.last_ - x.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(buffer_size()))//ͬ»º³åÇøÄÚ
{
cur_ += n;
}
else
{
difference_type node_offset;
if(offset > 0)
{
node_offset = difference_type(buffer_size());
}
else
node_offset = -difference_type((-offset - 1)/buffer_size())-1;
set_node(node_ + node_offset);
cur_ = first_ + (offset - node_offset * difference_type(buffer_size()));
}
return *this;
}
self operator+ (difference_type n) const
{
self tmp = *this;
return tmp += n;
}
self& operator-=(difference_type n)
{
return *this += -n;
}

self operator-(difference_type n) const
{
self tmp = *this;
return tmp -= n;
}

reference operator[](difference_type n) const
{
return *(*this + n);
}
bool operator==(const self& x) const
{
return cur_ == x.cur_;
}
bool operator!= (const self& x) const
{
return cur_ != x.cur_;
}
bool operator < (const self& x) const
{
return (node_ == x.node_) ?(cur_ < x.cur_) : (node_ < x.node_);
}
};

template <class T , size_t BufSiz = 0>
class deque
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef T& reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
public:
typedef deque_iterator<T, T&, T*, BufSiz> iterator;
protected:
typedef pointer* map_pointer;
protected:
iterator start_;
iterator finish_;

map_pointer map_;
size_type map_size_;

public:
iterator begin()
{
return start_;
}
iterator end()
{
return finish_;
}

reference operator[](size_type n)
{
return start_[difference_type(n)];
}
reference front()
{
return *start_;
}
reference back()
{
iterator tmp = finish_;
--tmp;
return *tmp;
}
size_type size()
{
return finish_ - start_;
}
size_type max_size() const
{
return size_type(-1);
}
bool empty() const
{
return finish_ == start_;
}
protected:
typedef simple_alloc<value_type> data_allocator;
typedef simple_alloc<pointer> map_allocator;
static size_t buffer_size()
{
return deque_buf_size(BufSiz, sizeof(T));
}
pointer allocate_node()
{
return data_allocator::allocate(buffer_size());
}
void deallocate_node(pointer n)
{
data_allocator::deallocate(n, buffer_size());
}
void create_map_and_nodes(size_type num_elements)
{
size_type num_nodes = num_elements/buffer_size()+1;

map_size_ = num_nodes + 2;
map_ = map_allocator::allocate(map_size_);

map_pointer nstart = map_ + (map_size_ - num_nodes) / 2;
map_pointer nfinish = nstart + num_nodes - 1;

map_pointer cur;
for (cur = nstart; cur <= nfinish; ++cur)
{
*cur = allocate_node();
}

start_.set_node(nstart);
finish_.set_node(nfinish);
start_.cur_ = start_.first_;
finish_.cur_ = finish_.first_ + num_elements % buffer_size();
}
void fill_initialize(size_type n, const value_type& value)
{
create_map_and_nodes(n);
map_pointer cur;
for (cur = start_.node_; cur < finish_.node_; ++cur)
uninitialized_fill(*cur, *cur + buffer_size(), value);
uninitialized_fill(finish_.first_, finish_.cur_, value);
}
public:
deque(int n, const value_type& value):start_(), finish_(), map_(0), map_size_(0)
{
fill_initialize(n, value);
}
~deque()
{
destroy(start_, finish_);
//  destroy_map_and_nodes();
}

void 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_)
copy(start_.node_, finish_.node_ + 1, new_nstart);
else
copy_backward(start_.node_, finish_.node_ + 1, new_nstart + old_num_nodes);
}
else
{
size_type new_map_size = map_size_ + max(map_size_, nodes_to_add) + 2;
map_pointer new_map = map_allocator::allocate(new_map_size);
new_nstart = new_map + (new_map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0);
copy(start_.node_, finish_.node_ + 1, new_nstart);
map_allocator::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);
}
void reserve_map_at_front(size_type nodes_to_add = 1)
{
if (nodes_to_add > start_.node_ - map_)
{
reallocate_map(nodes_to_add, true);
}
}
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 push_back_aux(const value_type& t)
{
value_type t_copy = t;
reserve_map_at_back();
*(finish_.node_ + 1) = allocate_node();
construct(finish_.cur_, t_copy);
finish_.set_node(finish_.node_ + 1);
finish_.cur_ = finish_.first_;
}
void push_back(const value_type& t)
{
if (finish_.cur_ != finish_.last_ - 1)
{
construct(finish_.cur_, t);
++finish_.cur_;
}
else
push_back_aux(t);
}
void push_front_aux(const value_type& t)
{
value_type t_copy = t;
reserve_map_at_front();
*(start_.node_ - 1) = allocate_node();
start_.set_node(start_.node_ - 1);
start_.cur_ = start_.last_ - 1;
construct(start_.cur_, t_copy);
}
void push_front(const value_type& t)
{
if (start_.cur_ != start_.first_)
{
construct(start_.cur_ - 1, t);
--start_.cur_;
}
else
{
pushi_front_aux(t);
}
}
void pop_back_aux()
{
deallocate_node(finish_.first_);
finish_.set_node(finish_.node_ - 1);
finish_.cur_ = finish_.last_ - 1;
destroy(finish_.cur_);
}
void pop_back()
{
if (finish_.cur_ != finish_.first_)
{
--finish_.cur_;
destroy(finish_.cur_);
}
else
pop_back_aux;
}
void pop_front_aux()
{
destroy(start_.cur_);
dellocate_node(start_.first_);
start_.set_node_(start_.node_ + 1);
start_.cur_ = start_.first_;
}
void pop_front()
{
if (start_.cur != start_.last_ - 1)
{
destroy(start_.cur_);
++start_.cur_;
}
else
pop_front_aux();
}
void clear()
{

for (map_pointer node = start_.node_ + 1; node < finish_.node_; ++node)
{

destroy(*node, *node + buffer_size());

data_allocator::deallocate(*node, buffer_size());
}

if (start_.node_ != finish_.node_)
{
destroy(start_.cur_, start_.last_);
destroy(finish_.first_, finish_.cur_);

data_allocator::deallocate(finish_.first_, buffer_size());
}
else
destroy(start_.cur_, finish_.cur_);

finish_ = start_;
}
iterator erase(iterator first, iterator last)
{
if (first == start_ && last == finish_)
{
clear();
return finish_;
}
else
{
difference_type n = last - first;
difference_type elems_before = first - start_;
if (elems_before < (size() - n) / 2)
{
copy_backward(start_, first, last);
iterator new_start = start_ + n;
destroy(start_, new_start);

for (map_pointer cur = start_.node_; cur < new_start.node_; ++cur)
data_allocator::deallocate(*cur, buffer_size());
start_ = new_start;
}
else
{
copy(last, finish_, first);
iterator new_finish = finish_ - n;
destroy(new_finish, finish_);

for (map_pointer cur = new_finish.node + 1; cur <= finish_.node_; ++cur)
data_allocator::deallocate(*cur, buffer_size());
finish_ = new_finish;
}
return start_ + elems_before;
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: