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; } } };
相关文章推荐
- Java中break return continue 区别
- HDU 2734 Quicksum [Ad Hoc]
- easyui tabs中href和content加载
- IOS探索之调整UILabel行高间距(利用iOS 6的特性来手动调整行间矩)
- HDOJ-1242(Rescue)(bfs+优先队列)
- 10030---java序列化和serialVersionUID
- POJ 2031 Building a Space Station
- 使用requestAnimationFrame做动画效果二
- 线程操作 NSOperation以及他的子类与 NSOperationQueue的搭配使用
- UEFI 模式ghost win10
- maven项目出现如下错误,求指点;CoreException: Could not calculate build plan:
- 通过实现一个TableView来理解iOS UI编程
- 生成缩略图的UIImage分类
- 除了UUID以外随机生成图片名的方法
- UI-GCD线程
- UI-NSOperation线程
- Android Studio BUILD FAILED finished with non-zero exit value
- JAVA:string中的copyValueOf方法
- Ubuntu LiveSuit V3.06不能烧写问题
- 系统API:UIView阻尼动画